@pierre/diffs 1.3.0-beta.9 → 1.3.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/components/CodeView.d.ts +12 -13
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +50 -58
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +10 -3
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +41 -10
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +37 -6
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +202 -19
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +7 -2
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +2 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +9 -5
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +14 -0
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +61 -3
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +14 -2
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +27 -2
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/edit/index.d.ts +5 -0
- package/dist/edit/index.js +3 -0
- package/dist/editor/command.d.ts +1 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +11 -0
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +6 -2
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +53 -12
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +51 -23
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +977 -241
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/languages.d.ts +26 -0
- package/dist/editor/languages.d.ts.map +1 -0
- package/dist/editor/languages.js +363 -0
- package/dist/editor/languages.js.map +1 -0
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +25 -26
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +5 -3
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +111 -91
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +3 -2
- package/dist/editor/matchBrackets.d.ts.map +1 -1
- package/dist/editor/matchBrackets.js +2 -10
- package/dist/editor/matchBrackets.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +2 -1
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +103 -39
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/platform.js +2 -0
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/popover.d.ts +25 -5
- package/dist/editor/popover.d.ts.map +1 -1
- package/dist/editor/popover.js +60 -14
- package/dist/editor/popover.js.map +1 -1
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +9 -2
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +31 -11
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +198 -70
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +4 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +9 -5
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/stateStorage.d.ts +15 -0
- package/dist/editor/stateStorage.d.ts.map +1 -0
- package/dist/editor/stateStorage.js +65 -0
- package/dist/editor/stateStorage.js.map +1 -0
- package/dist/editor/textDocument.d.ts +12 -77
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +76 -34
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +7 -12
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +40 -32
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/{tokenzier.d.ts → tokenizer.d.ts} +3 -3
- package/dist/editor/tokenizer.d.ts.map +1 -0
- package/dist/editor/{tokenzier.js → tokenizer.js} +170 -50
- package/dist/editor/tokenizer.js.map +1 -0
- package/dist/editor/utils.js +1 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +6 -5
- package/dist/managers/InteractionManager.d.ts +18 -7
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +154 -99
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
- package/dist/managers/UniversalRenderingManager.js +1 -2
- package/dist/managers/UniversalRenderingManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +13 -13
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +37 -28
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditContext.d.ts +20 -0
- package/dist/react/EditContext.d.ts.map +1 -0
- package/dist/react/EditContext.js +20 -0
- package/dist/react/EditContext.js.map +1 -0
- package/dist/react/File.d.ts +2 -1
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +3 -2
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +2 -2
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +3 -2
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +2 -2
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +3 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +2 -2
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +3 -2
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +1 -1
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +3 -3
- package/dist/react/types.d.ts +9 -1
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +5 -3
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +24 -34
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +5 -3
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +23 -33
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +4 -4
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +41 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +167 -29
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +20 -1
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +119 -29
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +3 -1
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/ssr/preloadFile.d.ts.map +1 -1
- package/dist/ssr/preloadFile.js +2 -0
- package/dist/ssr/preloadFile.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/types.d.ts +192 -42
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/annotationHelpers.d.ts +20 -0
- package/dist/utils/annotationHelpers.d.ts.map +1 -0
- package/dist/utils/annotationHelpers.js +29 -0
- package/dist/utils/annotationHelpers.js.map +1 -0
- package/dist/utils/computeFileOffsets.d.ts.map +1 -1
- package/dist/utils/computeFileOffsets.js +34 -5
- package/dist/utils/computeFileOffsets.js.map +1 -1
- package/dist/utils/editSessionHunks.d.ts +66 -0
- package/dist/utils/editSessionHunks.d.ts.map +1 -0
- package/dist/utils/editSessionHunks.js +437 -0
- package/dist/utils/editSessionHunks.js.map +1 -0
- package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.js +2 -1
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
- package/dist/utils/getFileRendererOptions.js +2 -1
- package/dist/utils/getFileRendererOptions.js.map +1 -1
- package/dist/utils/getHunkSideBoundaries.d.ts +7 -0
- package/dist/utils/getHunkSideBoundaries.d.ts.map +1 -0
- package/dist/utils/getHunkSideBoundaries.js +12 -0
- package/dist/utils/getHunkSideBoundaries.js.map +1 -0
- package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js +2 -1
- package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
- package/dist/utils/hydratePartialDiff.js +4 -3
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/isGutterUtilityPath.d.ts +5 -0
- package/dist/utils/isGutterUtilityPath.d.ts.map +1 -0
- package/dist/utils/isGutterUtilityPath.js +12 -0
- package/dist/utils/isGutterUtilityPath.js.map +1 -0
- package/dist/utils/iterateOverDiff.d.ts.map +1 -1
- package/dist/utils/iterateOverDiff.js +17 -12
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +9 -6
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +6 -3
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/realignChangeContent.d.ts +33 -0
- package/dist/utils/realignChangeContent.d.ts.map +1 -0
- package/dist/utils/realignChangeContent.js +148 -0
- package/dist/utils/realignChangeContent.js.map +1 -0
- package/dist/utils/renderDiffWithHighlighter.js +1 -1
- package/dist/utils/resolveRegion.d.ts.map +1 -1
- package/dist/utils/resolveRegion.js +18 -2
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.d.ts +7 -3
- package/dist/utils/shouldUseTokenTransformer.d.ts.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.js +1 -1
- package/dist/utils/shouldUseTokenTransformer.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +8 -2
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +9 -7
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/virtualDiffLayout.d.ts +42 -2
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +101 -7
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +2 -1
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +3 -0
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/worker-portable.js +60 -20
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +61 -19
- package/dist/worker/worker.js.map +1 -1
- package/package.json +10 -7
- package/dist/editor/index.d.ts +0 -3
- package/dist/editor/index.js +0 -3
- package/dist/editor/tokenzier.d.ts.map +0 -1
- package/dist/editor/tokenzier.js.map +0 -1
- package/dist/react/EditorContext.d.ts +0 -15
- package/dist/react/EditorContext.d.ts.map +0 -1
- package/dist/react/EditorContext.js +0 -23
- package/dist/react/EditorContext.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPoolManager.js","names":[],"sources":["../../src/worker/WorkerPoolManager.ts"],"sourcesContent":["import LRUMapPkg from 'lru_map';\n\nimport { DEFAULT_THEMES } from '../constants';\nimport { getResolvedLanguages } from '../highlighter/languages/getResolvedLanguages';\nimport { hasResolvedLanguages } from '../highlighter/languages/hasResolvedLanguages';\nimport { resolveLanguages } from '../highlighter/languages/resolveLanguages';\nimport { getSharedHighlighter } from '../highlighter/shared_highlighter';\nimport { attachResolvedThemes } from '../highlighter/themes/attachResolvedThemes';\nimport { getResolvedThemes } from '../highlighter/themes/getResolvedThemes';\nimport { hasResolvedThemes } from '../highlighter/themes/hasResolvedThemes';\nimport { resolveThemes } from '../highlighter/themes/resolveThemes';\nimport type {\n DiffsHighlighter,\n FileContents,\n FileDiffMetadata,\n HighlighterTypes,\n HunkExpansionRegion,\n RenderDiffOptions,\n RenderDiffResult,\n RenderFileOptions,\n RenderFileResult,\n SupportedLanguages,\n ThemedDiffResult,\n ThemedFileResult,\n ThemeRegistrationResolved,\n} from '../types';\nimport { areDiffRenderOptionsEqual } from '../utils/areDiffRenderOptionsEqual';\nimport { areDiffTargetsEqual } from '../utils/areDiffTargetsEqual';\nimport { areFileRenderOptionsEqual } from '../utils/areFileRenderOptionsEqual';\nimport { areFilesEqual } from '../utils/areFilesEqual';\nimport { areThemesEqual } from '../utils/areThemesEqual';\nimport {\n getCustomExtensionsMap,\n getCustomExtensionsVersion,\n getFiletypeFromFileName,\n} from '../utils/getFiletypeFromFileName';\nimport { getThemes } from '../utils/getThemes';\nimport { isDiffPlainText } from '../utils/isDiffPlainText';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { renderDiffWithHighlighter } from '../utils/renderDiffWithHighlighter';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport type {\n AllWorkerTasks,\n DiffRendererInstance,\n FileRendererInstance,\n InitializeWorkerRequest,\n InitializeWorkerTask,\n RenderDiffRequest,\n RenderDiffTask,\n RenderFileRequest,\n RenderFileTask,\n ResolvedLanguage,\n SetRenderOptionsWorkerTask,\n SubmitRequest,\n WorkerInitializationRenderOptions,\n WorkerPoolOptions,\n WorkerRenderingOptions,\n WorkerRequestId,\n WorkerResponse,\n WorkerStats,\n} from './types';\n\nconst IGNORE_RESPONSE = Symbol('IGNORE_RESPONSE');\n\nclass WorkerPoolTerminatedError extends Error {\n constructor() {\n super('WorkerPoolManager: operation canceled because the pool terminated');\n }\n}\n\nclass WorkerPoolTaskCanceledError extends Error {\n constructor() {\n super('WorkerPoolManager: operation canceled before the task completed');\n }\n}\n\ninterface GetCachesResult {\n fileCache: LRUMapPkg.LRUMap<string, RenderFileResult>;\n diffCache: LRUMapPkg.LRUMap<string, RenderDiffResult>;\n}\n\ninterface ManagedWorker {\n worker: Worker;\n requestId: string | undefined;\n pendingSetupRequestId: WorkerRequestId | undefined;\n initialized: boolean;\n langs: Set<SupportedLanguages>;\n customExtensionsVersion: number;\n}\n\ninterface ThemeSubscriber {\n onThemeChange(): void;\n}\n\ntype RenderTask = RenderFileTask | RenderDiffTask;\n\ntype RenderTaskInstance = FileRendererInstance | DiffRendererInstance;\n\nexport class WorkerPoolManager {\n private highlighter: DiffsHighlighter | undefined;\n private readonly preferredHighlighter: HighlighterTypes;\n private renderOptions: WorkerRenderingOptions;\n private renderOptionsRequestVersion = 0;\n private renderOptionsVersion = 0;\n private initialized: Promise<void> | boolean = false;\n private workers: ManagedWorker[] = [];\n // Tasks that are waiting to get processed by a worker\n private queuedTasks: RenderTask[] = [];\n private queuedTaskByInstance = new Map<RenderTaskInstance, RenderTask>();\n\n // Tasks that map to highlightKey are essentially singular, so we only\n // need one map to include queued and active\n private taskByHighlightKey = new Map<string, RenderTask>();\n\n // Tasks that have already been sent to a worker and are awaiting a response.\n private activeTaskById = new Map<WorkerRequestId, AllWorkerTasks>();\n private activeRequestByInstance = new Map<\n RenderTaskInstance,\n WorkerRequestId\n >();\n\n private nextRequestId = 0;\n private themeSubscribers = new Set<ThemeSubscriber>();\n private workersFailed = false;\n private statSubscribers = new Set<(stats: WorkerStats) => unknown>();\n private fileCache: LRUMapPkg.LRUMap<string, RenderFileResult>;\n private diffCache: LRUMapPkg.LRUMap<string, RenderDiffResult>;\n private _queuedBroadcast: number | undefined;\n // Incremented on terminate so async lifecycle work can identify stale results.\n private lifecycleGeneration = 0;\n\n constructor(\n private options: WorkerPoolOptions,\n {\n langs,\n theme = DEFAULT_THEMES,\n useTokenTransformer = false,\n lineDiffType = 'word-alt',\n maxLineDiffLength = 1000,\n tokenizeMaxLineLength = 1000,\n preferredHighlighter = 'shiki-js',\n }: WorkerInitializationRenderOptions\n ) {\n this.preferredHighlighter = preferredHighlighter;\n this.renderOptions = {\n theme,\n useTokenTransformer,\n lineDiffType,\n maxLineDiffLength,\n tokenizeMaxLineLength,\n };\n this.fileCache = new LRUMapPkg.LRUMap(options.totalASTLRUCacheSize ?? 100);\n this.diffCache = new LRUMapPkg.LRUMap(options.totalASTLRUCacheSize ?? 100);\n this.queueInitialization(langs);\n }\n\n public isWorkingPool(): boolean {\n return !this.workersFailed;\n }\n\n public getFileResultCache(file: FileContents): RenderFileResult | undefined {\n return file.cacheKey != null\n ? this.fileCache.get(file.cacheKey)\n : undefined;\n }\n\n public getDiffResultCache(\n diff: FileDiffMetadata\n ): RenderDiffResult | undefined {\n return diff.cacheKey != null\n ? this.diffCache.get(diff.cacheKey)\n : undefined;\n }\n\n public inspectCaches(): GetCachesResult {\n const { fileCache, diffCache } = this;\n return { fileCache, diffCache };\n }\n\n public evictFileFromCache(cacheKey: string): boolean {\n try {\n return this.fileCache.delete(cacheKey) !== undefined;\n } finally {\n this.queueBroadcastStateChanges();\n }\n }\n\n public evictDiffFromCache(cacheKey: string): boolean {\n try {\n return this.diffCache.delete(cacheKey) !== undefined;\n } finally {\n this.queueBroadcastStateChanges();\n }\n }\n\n async setRenderOptions({\n theme = this.renderOptions.theme ?? DEFAULT_THEMES,\n useTokenTransformer = this.renderOptions.useTokenTransformer ?? false,\n lineDiffType = this.renderOptions.lineDiffType ?? 'word-alt',\n maxLineDiffLength = this.renderOptions.maxLineDiffLength ?? 1000,\n tokenizeMaxLineLength = this.renderOptions.tokenizeMaxLineLength ?? 1000,\n }: Partial<WorkerRenderingOptions>): Promise<void> {\n const { lifecycleGeneration } = this;\n const renderOptionsRequestVersion = ++this.renderOptionsRequestVersion;\n const isCurrentRequest = (): boolean =>\n this.isCurrentLifecycle(lifecycleGeneration) &&\n this.renderOptionsRequestVersion === renderOptionsRequestVersion;\n try {\n const newRenderOptions: WorkerRenderingOptions = {\n theme,\n useTokenTransformer,\n lineDiffType,\n maxLineDiffLength,\n tokenizeMaxLineLength,\n };\n if (!this.isInitialized()) {\n await this.initialize();\n }\n if (\n !isCurrentRequest() ||\n areDiffRenderOptionsEqual(newRenderOptions, this.renderOptions)\n ) {\n return;\n }\n\n const themeNames = getThemes(theme);\n let resolvedThemes: ThemeRegistrationResolved[] = [];\n if (!areThemesEqual(newRenderOptions.theme, this.renderOptions.theme)) {\n if (hasResolvedThemes(themeNames)) {\n resolvedThemes = getResolvedThemes(themeNames);\n } else {\n resolvedThemes = await resolveThemes(themeNames);\n }\n }\n\n if (!isCurrentRequest()) {\n return;\n }\n\n if (this.highlighter != null) {\n attachResolvedThemes(resolvedThemes, this.highlighter);\n } else {\n const highlighter = await getSharedHighlighter({\n themes: themeNames,\n langs: ['text'],\n preferredHighlighter: this.preferredHighlighter,\n });\n if (!isCurrentRequest()) {\n return;\n }\n this.highlighter = highlighter;\n }\n\n const workerSetup = this.setRenderOptionsOnWorkers(\n newRenderOptions,\n resolvedThemes\n );\n\n this.renderOptions = newRenderOptions;\n this.renderOptionsVersion++;\n this.diffCache.clear();\n this.fileCache.clear();\n this.invalidateRenderTasks();\n\n for (const instance of this.themeSubscribers) {\n instance.onThemeChange();\n }\n\n await workerSetup;\n } catch (error) {\n if (error instanceof WorkerPoolTerminatedError || !isCurrentRequest()) {\n return;\n }\n throw error;\n }\n }\n\n public getFileRenderOptions(): RenderFileOptions {\n const { tokenizeMaxLineLength, theme, useTokenTransformer } =\n this.renderOptions;\n return { theme, useTokenTransformer, tokenizeMaxLineLength };\n }\n\n public getDiffRenderOptions(): RenderDiffOptions {\n return { ...this.renderOptions };\n }\n\n private async setRenderOptionsOnWorkers(\n renderOptions: WorkerRenderingOptions,\n resolvedThemes: ThemeRegistrationResolved[]\n ): Promise<void> {\n if (this.workersFailed) {\n return;\n }\n if (!this.isInitialized()) {\n await this.initialize();\n }\n const taskPromises: Promise<void>[] = [];\n for (const managedWorker of this.workers) {\n if (!managedWorker.initialized) {\n console.log({ managedWorker });\n throw new Error(\n 'setRenderOptionsOnWorkers: Somehow we have an uninitialized worker'\n );\n }\n taskPromises.push(\n new Promise<void>((resolve, reject) => {\n const id = this.generateRequestId();\n const task: SetRenderOptionsWorkerTask = {\n type: 'set-render-options',\n id,\n request: {\n type: 'set-render-options',\n id,\n renderOptions,\n resolvedThemes,\n },\n resolve,\n reject,\n requestStart: Date.now(),\n };\n // Render-option updates are posted immediately, but the worker stays\n // unavailable for new render work until it acknowledges this message.\n this.activeTaskById.set(id, task);\n managedWorker.pendingSetupRequestId = id;\n managedWorker.worker.postMessage(task.request);\n })\n );\n }\n await Promise.all(taskPromises);\n }\n\n public subscribeToThemeChanges(instance: ThemeSubscriber): () => void {\n this.themeSubscribers.add(instance);\n this.queueBroadcastStateChanges();\n return () => {\n this.unsubscribeToThemeChanges(instance);\n this.queueBroadcastStateChanges();\n };\n }\n\n public unsubscribeToThemeChanges(instance: ThemeSubscriber): void {\n this.themeSubscribers.delete(instance);\n this.queueBroadcastStateChanges();\n }\n\n public subscribeToStatChanges(\n callback: (stats: WorkerStats) => unknown\n ): () => void {\n this.statSubscribers.add(callback);\n callback(this.getStats());\n return () => {\n this.statSubscribers.delete(callback);\n };\n }\n\n private queueBroadcastStateChanges() {\n if (this._queuedBroadcast != null) return;\n this._queuedBroadcast = requestAnimationFrame(this._broadcastStateChanges);\n }\n\n private _broadcastStateChanges = () => {\n if (this._queuedBroadcast != null) {\n cancelAnimationFrame(this._queuedBroadcast);\n this._queuedBroadcast = undefined;\n }\n const stats = this.getStats();\n for (const callback of this.statSubscribers) {\n callback(stats);\n }\n };\n\n public cleanUpTasks(instance: RenderTaskInstance): void {\n this.detachInstanceFromQueuedTasks(instance);\n const requestId = this.activeRequestByInstance.get(instance);\n if (requestId != null) {\n const task = this.activeTaskById.get(requestId);\n if (isRenderTask(task)) {\n this.detachInstanceFromRenderTask(task, instance);\n if (!task.primeCache && task.instances.size === 0) {\n this.removeActiveTask(task);\n }\n } else {\n this.activeTaskById.delete(requestId);\n }\n }\n this.activeRequestByInstance.delete(instance);\n this.queueBroadcastStateChanges();\n }\n\n public isInitialized(): boolean {\n return this.initialized === true;\n }\n\n public async initialize(languages: SupportedLanguages[] = []): Promise<void> {\n if (this.initialized === true) {\n return;\n } else if (this.initialized === false) {\n const { lifecycleGeneration } = this;\n this.initialized = new Promise((resolve, reject) => {\n void (async () => {\n try {\n const themes = getThemes(this.renderOptions.theme);\n let resolvedThemes: ThemeRegistrationResolved[] = [];\n if (hasResolvedThemes(themes)) {\n resolvedThemes = getResolvedThemes(themes);\n } else {\n resolvedThemes = await resolveThemes(themes);\n }\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n resolve();\n return;\n }\n\n let resolvedLanguages: ResolvedLanguage[] = [];\n if (hasResolvedLanguages(languages)) {\n resolvedLanguages = getResolvedLanguages(languages);\n } else {\n resolvedLanguages = await resolveLanguages(languages);\n }\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n resolve();\n return;\n }\n\n const [highlighter] = await Promise.all([\n getSharedHighlighter({\n themes,\n langs: ['text', ...languages],\n preferredHighlighter: this.preferredHighlighter,\n }),\n this.initializeWorkers(resolvedThemes, resolvedLanguages),\n ]);\n\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n this.terminateWorkers();\n resolve();\n return;\n }\n this.highlighter = highlighter;\n this.initialized = true;\n this.diffCache.clear();\n this.fileCache.clear();\n this.drainQueue();\n this.queueBroadcastStateChanges();\n resolve();\n } catch (e) {\n if (\n e instanceof WorkerPoolTerminatedError ||\n !this.isCurrentLifecycle(lifecycleGeneration)\n ) {\n resolve();\n return;\n }\n this.initialized = false;\n this.workersFailed = true;\n for (const task of this.queuedTasks) {\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(e));\n }\n this.queueBroadcastStateChanges();\n reject(e);\n }\n })();\n });\n this.queueBroadcastStateChanges();\n } else {\n return this.initialized;\n }\n }\n\n private async initializeWorkers(\n resolvedThemes: ThemeRegistrationResolved[],\n resolvedLanguages: ResolvedLanguage[]\n ): Promise<void> {\n this.workersFailed = false;\n const initPromises: Promise<unknown>[] = [];\n const customExtensionVersion = getCustomExtensionsVersion();\n const customExtensionMap =\n customExtensionVersion > 0 ? getCustomExtensionsMap() : undefined;\n if (this.workers.length > 0) {\n this.terminateWorkers();\n }\n for (let i = 0; i < (this.options.poolSize ?? 8); i++) {\n const worker = this.options.workerFactory();\n const managedWorker: ManagedWorker = {\n worker,\n requestId: undefined,\n pendingSetupRequestId: undefined,\n initialized: false,\n langs: new Set(['text', ...resolvedLanguages.map(({ name }) => name)]),\n customExtensionsVersion: 0,\n };\n worker.addEventListener(\n 'message',\n (event: MessageEvent<WorkerResponse>) => {\n this.handleWorkerMessage(managedWorker, event.data);\n }\n );\n worker.addEventListener('error', (error) =>\n console.error('Worker error:', error, managedWorker)\n );\n this.workers.push(managedWorker);\n initPromises.push(\n new Promise<void>((resolve, reject) => {\n const id = this.generateRequestId();\n const task: InitializeWorkerTask = {\n type: 'initialize',\n id,\n request: {\n type: 'initialize',\n id,\n renderOptions: this.renderOptions,\n preferredHighlighter: this.preferredHighlighter,\n resolvedThemes,\n resolvedLanguages,\n customExtensionsVersion:\n customExtensionMap != null ? customExtensionVersion : undefined,\n customExtensionMap,\n },\n resolve() {\n managedWorker.initialized = true;\n resolve();\n },\n reject,\n requestStart: Date.now(),\n };\n this.activeTaskById.set(id, task);\n this.executeTask(managedWorker, task);\n })\n );\n }\n await Promise.all(initPromises);\n }\n\n private drainQueue = () => {\n this._queuedDrain = undefined;\n // If we are initializing or things got cancelled while initializing, we\n // should not attempt to drain the queue\n if (this.initialized !== true || this.queuedTasks.length === 0) {\n return;\n }\n for (let i = 0; i < this.queuedTasks.length; ) {\n const task = this.queuedTasks[i];\n // If any instance has a request in progress, we should wait for it to\n // finish before starting work that would notify that instance.\n if (this.hasActiveRequest(task)) {\n i++;\n continue;\n }\n const langs = getLangsFromTask(task);\n const availableWorker = this.getAvailableWorker(langs);\n if (availableWorker == null) {\n break;\n }\n this.queuedTasks.splice(i, 1);\n this.assignWorkerToTask(task, availableWorker);\n void this.resolveLanguagesAndExecuteTask(availableWorker, task, langs);\n }\n this.queueBroadcastStateChanges();\n };\n\n public highlightFileAST(\n instance: FileRendererInstance,\n file: FileContents\n ): void {\n const cachedResult = this.getFileResultCache(file);\n // If we've already highlighted the file or it's plain text, we should not\n // attempt to highlight. This should be mostly never hit, but it's just an\n // extra level of safety\n if (\n isFilePlainText(file) ||\n (cachedResult != null &&\n areFileRenderOptionsEqual(\n cachedResult.options,\n this.getFileRenderOptions()\n ))\n ) {\n return;\n }\n if (!this.hasMatchingFileInstanceTask(instance, file)) {\n this.submitTask(instance, { type: 'file', file });\n }\n }\n\n public primeFileHighlightCache(file: FileContents): Promise<void> {\n if (!this.isWorkingPool()) {\n return Promise.reject(\n new Error(\n 'WorkerPoolManager.primeFileHighlightCache: worker pool is not working'\n )\n );\n }\n\n const task = this.getOrCreateFileHighlightCacheTask(file);\n return task != null\n ? this.createRenderTaskCallbacks(task)\n : Promise.resolve();\n }\n\n private getOrCreateFileHighlightCacheTask(\n file: FileContents\n ): RenderFileTask | undefined {\n if (file.cacheKey == null) {\n console.warn(\n `WorkerPoolManager.primeFileHighlightCache: priming highlight cache requires file.cacheKey; skipping \"${file.name}\".`\n );\n return undefined;\n }\n const cachedResult = this.getFileResultCache(file);\n const highlightKey = this.getFileHighlightKey(file);\n if (\n highlightKey == null ||\n isFilePlainText(file) ||\n (cachedResult != null &&\n areFileRenderOptionsEqual(\n cachedResult.options,\n this.getFileRenderOptions()\n ))\n ) {\n return undefined;\n }\n const existingTask = this.getTaskByHighlightKey(highlightKey);\n if (existingTask != null) {\n existingTask.primeCache = true;\n return existingTask.type === 'file' ? existingTask : undefined;\n } else {\n const task = this.submitCacheTask({ type: 'file', file }, highlightKey);\n return task.type === 'file' ? task : undefined;\n }\n }\n\n public getPlainFileAST(\n file: FileContents,\n startingLine: number,\n totalLines: number,\n lines?: string[]\n ): ThemedFileResult | undefined {\n if (this.highlighter == null) {\n this.queueInitialization();\n return undefined;\n }\n return renderFileWithHighlighter(\n file,\n this.highlighter,\n this.renderOptions,\n { forcePlainText: true, startingLine, totalLines, lines }\n );\n }\n\n public highlightDiffAST(\n instance: DiffRendererInstance,\n diff: FileDiffMetadata\n ): void {\n const cachedResult = this.getDiffResultCache(diff);\n // If we've already highlighted the diff or it's plain text, we should not\n // attempt to highlight. This should be mostly never hit, but it's just an\n // extra level of safety\n if (\n isDiffPlainText(diff) ||\n (cachedResult != null &&\n areDiffRenderOptionsEqual(\n cachedResult.options,\n this.getDiffRenderOptions()\n ))\n ) {\n return;\n }\n if (!this.hasMatchingDiffInstanceTask(instance, diff)) {\n this.submitTask(instance, { type: 'diff', diff });\n }\n }\n\n public primeDiffHighlightCache(diff: FileDiffMetadata): Promise<void> {\n if (!this.isWorkingPool()) {\n return Promise.reject(\n new Error(\n 'WorkerPoolManager.primeDiffHighlightCache: worker pool is not working'\n )\n );\n }\n\n const task = this.getOrCreateDiffHighlightCacheTask(diff);\n return task != null\n ? this.createRenderTaskCallbacks(task)\n : Promise.resolve();\n }\n\n private getOrCreateDiffHighlightCacheTask(\n diff: FileDiffMetadata\n ): RenderDiffTask | undefined {\n if (diff.cacheKey == null) {\n console.warn(\n `WorkerPoolManager.primeDiffHighlightCache: priming highlight cache requires diff.cacheKey; skipping \"${diff.prevName ?? diff.name}\" -> \"${diff.name}\".`\n );\n return undefined;\n }\n const cachedResult = this.getDiffResultCache(diff);\n const highlightKey = this.getDiffHighlightKey(diff);\n if (\n highlightKey == null ||\n isDiffPlainText(diff) ||\n (cachedResult != null &&\n areDiffRenderOptionsEqual(\n cachedResult.options,\n this.getDiffRenderOptions()\n ))\n ) {\n return undefined;\n }\n const existingTask = this.getTaskByHighlightKey(highlightKey);\n if (existingTask != null) {\n existingTask.primeCache = true;\n return existingTask.type === 'diff' ? existingTask : undefined;\n } else {\n const task = this.submitCacheTask({ type: 'diff', diff }, highlightKey);\n return task.type === 'diff' ? task : undefined;\n }\n }\n\n public getPlainDiffAST(\n diff: FileDiffMetadata,\n startingLine: number,\n totalLines: number,\n expandedHunks?: Map<number, HunkExpansionRegion> | true,\n collapsedContextThreshold?: number\n ): ThemedDiffResult | undefined {\n return this.highlighter != null\n ? renderDiffWithHighlighter(diff, this.highlighter, this.renderOptions, {\n forcePlainText: true,\n startingLine,\n totalLines,\n expandedHunks,\n collapsedContextThreshold,\n })\n : undefined;\n }\n\n public terminate(): void {\n this.lifecycleGeneration++;\n this.cancelActiveWorkerTasks();\n this.terminateWorkers();\n const error = new WorkerPoolTerminatedError();\n for (const task of this.queuedTasks) {\n this.rejectRenderTaskCallbacks(task, error);\n }\n this.fileCache.clear();\n this.diffCache.clear();\n this.activeRequestByInstance.clear();\n this.queuedTasks.length = 0;\n this.queuedTaskByInstance.clear();\n this.taskByHighlightKey.clear();\n this.activeTaskById.clear();\n this.highlighter = undefined;\n this.initialized = false;\n this.workersFailed = false;\n this.queueBroadcastStateChanges();\n }\n\n private isCurrentLifecycle(lifecycleGeneration: number): boolean {\n return this.lifecycleGeneration === lifecycleGeneration;\n }\n\n private queueInitialization(languages?: SupportedLanguages[]): void {\n void this.initialize(languages).catch((error) => {\n console.error(error);\n });\n }\n\n private cancelActiveWorkerTasks(): void {\n const error = new WorkerPoolTerminatedError();\n for (const task of this.activeTaskById.values()) {\n if ('reject' in task) {\n task.reject(error);\n } else if (isRenderTask(task)) {\n this.rejectRenderTaskCallbacks(task, error);\n }\n }\n }\n\n private terminateWorkers() {\n for (const managedWorker of this.workers) {\n managedWorker.worker.terminate();\n }\n this.workers.length = 0;\n }\n\n public getStats(): WorkerStats {\n return {\n managerState: (() => {\n if (this.initialized === false) {\n return 'waiting';\n }\n if (this.initialized !== true) {\n return 'initializing';\n }\n return 'initialized';\n })(),\n totalWorkers: this.workers.length,\n workersFailed: this.workersFailed,\n busyWorkers: this.workers.filter(\n (w) => w.requestId != null || w.pendingSetupRequestId != null\n ).length,\n queuedTasks: this.queuedTasks.length,\n activeTasks: this.activeTaskById.size,\n themeSubscribers: this.themeSubscribers.size,\n fileCacheSize: this.fileCache.size,\n diffCacheSize: this.diffCache.size,\n };\n }\n\n private submitTask(\n instance: FileRendererInstance,\n request: Omit<RenderFileRequest, 'id'>\n ): void;\n private submitTask(\n instance: DiffRendererInstance,\n request: Omit<RenderDiffRequest, 'id'>\n ): void;\n private submitTask(\n instance: FileRendererInstance | DiffRendererInstance,\n request: SubmitRequest\n ): void {\n if (this.initialized === false) {\n this.queueInitialization();\n }\n\n const highlightKey = this.getHighlightKeyForRequest(request);\n const existingTask =\n highlightKey != null\n ? this.getTaskByHighlightKey(highlightKey)\n : undefined;\n if (existingTask != null) {\n this.detachInstanceFromQueuedTasks(instance, existingTask);\n this.addInstanceToTask(existingTask, instance);\n this.queueBroadcastStateChanges();\n return;\n }\n\n this.detachInstanceFromQueuedTasks(instance);\n const id = this.generateRequestId();\n const requestStart = Date.now();\n const { renderOptionsVersion } = this;\n const task: RenderTask = (() => {\n switch (request.type) {\n case 'file':\n return {\n type: 'file',\n id,\n request: { ...request, id },\n instances: new Set([instance as FileRendererInstance]),\n primeCache: false,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n case 'diff':\n return {\n type: 'diff',\n id,\n request: { ...request, id },\n instances: new Set([instance as DiffRendererInstance]),\n primeCache: false,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n }\n })();\n this.enqueueRenderTask(task, instance);\n }\n\n private submitCacheTask(\n request: SubmitRequest,\n highlightKey: string\n ): RenderTask {\n if (this.initialized === false) {\n this.queueInitialization();\n }\n const id = this.generateRequestId();\n const requestStart = Date.now();\n const { renderOptionsVersion } = this;\n const task: RenderTask = (() => {\n switch (request.type) {\n case 'file':\n return {\n type: 'file',\n id,\n request: { ...request, id },\n instances: new Set<FileRendererInstance>(),\n primeCache: true,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n case 'diff':\n return {\n type: 'diff',\n id,\n request: { ...request, id },\n instances: new Set<DiffRendererInstance>(),\n primeCache: true,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n }\n })();\n this.enqueueRenderTask(task);\n return task;\n }\n\n private enqueueRenderTask(\n task: RenderTask,\n instance?: RenderTaskInstance\n ): void {\n this.queuedTasks.push(task);\n if (instance != null) {\n this.queuedTaskByInstance.set(instance, task);\n }\n if (task.highlightKey != null) {\n this.taskByHighlightKey.set(task.highlightKey, task);\n }\n this.queueDrain();\n }\n\n private async resolveLanguagesAndExecuteTask(\n availableWorker: ManagedWorker,\n task: RenderFileTask | RenderDiffTask,\n langs: SupportedLanguages[]\n ): Promise<void> {\n try {\n // Add resolved languages if required\n const workerMissingLangs = langs.filter(\n (lang) => !availableWorker.langs.has(lang)\n );\n\n if (workerMissingLangs.length > 0) {\n if (hasResolvedLanguages(workerMissingLangs)) {\n task.request.resolvedLanguages =\n getResolvedLanguages(workerMissingLangs);\n } else {\n task.request.resolvedLanguages =\n await resolveLanguages(workerMissingLangs);\n }\n }\n // If the task has been cleaned up after awaiting language resolving,\n // lets fully clean it up\n if (!this.activeTaskById.has(task.id)) {\n if (availableWorker.requestId === task.id) {\n this.cleanWorkerAndTask(availableWorker, task);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n return;\n }\n this.executeTask(availableWorker, task);\n } catch (error) {\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(error));\n this.cleanWorkerAndTask(availableWorker, task);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n }\n\n private handleWorkerMessage(\n managedWorker: ManagedWorker,\n response: WorkerResponse\n ): void {\n const task = this.activeTaskById.get(response.id);\n try {\n if (task == null) {\n // If we can't find a task for this response, it probably means the\n // component has been unmounted, so we should silently ignore it\n throw IGNORE_RESPONSE;\n } else if (response.type === 'error') {\n const error = new Error(response.error);\n if (response.stack) {\n error.stack = response.stack;\n }\n if ('reject' in task) {\n task.reject(error);\n } else if (isRenderTask(task)) {\n this.notifyHighlightError(task, error);\n this.rejectRenderTaskCallbacks(task, error);\n } else {\n throw new Error('handleWorkerMessage: unknown task type');\n }\n throw error;\n } else {\n switch (response.requestType) {\n case 'initialize':\n if (task.type !== 'initialize') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n this.syncCustomExtensionVersion(managedWorker, task.request);\n task.resolve();\n break;\n case 'set-render-options':\n if (task.type !== 'set-render-options') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n task.resolve();\n break;\n case 'file': {\n if (task.type !== 'file') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n const { result, options } = response;\n if (\n !this.isCurrentRenderTask(task) ||\n !areFileRenderOptionsEqual(options, this.getFileRenderOptions())\n ) {\n throw IGNORE_RESPONSE;\n }\n const { request } = task;\n this.syncCustomExtensionVersion(managedWorker, request);\n if (task.cacheKeyAtDispatch != null) {\n this.fileCache.set(task.cacheKeyAtDispatch, { result, options });\n }\n this.resolveRenderTaskCallbacks(task);\n this.notifyFileInstances(task, result, options);\n break;\n }\n case 'diff': {\n if (task.type !== 'diff') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n const { result, options } = response;\n if (\n !this.isCurrentRenderTask(task) ||\n !areDiffRenderOptionsEqual(options, this.getDiffRenderOptions())\n ) {\n throw IGNORE_RESPONSE;\n }\n const { request } = task;\n this.syncCustomExtensionVersion(managedWorker, request);\n if (task.cacheKeyAtDispatch != null) {\n this.diffCache.set(task.cacheKeyAtDispatch, { result, options });\n }\n this.resolveRenderTaskCallbacks(task);\n this.notifyDiffInstances(task, result, options);\n break;\n }\n }\n }\n } catch (error) {\n if (error !== IGNORE_RESPONSE) {\n console.error(error, task, response);\n }\n }\n\n this.cleanWorkerAndTask(managedWorker, task, response.id);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n // We queue drain so that potentially multiple workers can free up\n // allowing for better language matches if possible\n this.queueDrain();\n }\n }\n\n private _queuedDrain: Promise<void> | undefined;\n private queueDrain() {\n if (this._queuedDrain != null) return;\n this._queuedDrain = Promise.resolve().then(this.drainQueue);\n this.queueBroadcastStateChanges();\n }\n\n private assignWorkerToTask(\n task: AllWorkerTasks,\n managedWorker: ManagedWorker\n ) {\n managedWorker.requestId = task.id;\n if (isRenderTask(task)) {\n this.clearQueuedInstanceRequests(task);\n this.trackInstanceRequests(task);\n }\n this.activeTaskById.set(task.id, task);\n }\n\n private cleanWorkerAndTask(\n managedWorker: ManagedWorker,\n task?: AllWorkerTasks,\n requestId: WorkerRequestId | undefined = task?.id\n ) {\n if (managedWorker.requestId === requestId) {\n managedWorker.requestId = undefined;\n }\n if (managedWorker.pendingSetupRequestId === requestId) {\n managedWorker.pendingSetupRequestId = undefined;\n }\n if (task != null) {\n if (isRenderTask(task)) {\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearInstanceRequests(task);\n this.clearHighlightKey(task);\n }\n this.activeTaskById.delete(task.id);\n }\n }\n\n private executeTask(\n managedWorker: ManagedWorker,\n task: AllWorkerTasks\n ): void {\n if (shouldSyncCustomExtensions(task.request)) {\n this.maybeAttachCustomExtensions(managedWorker, task.request);\n }\n if (!this.activeTaskById.has(task.id)) {\n this.assignWorkerToTask(task, managedWorker);\n }\n for (const lang of getLangsFromTask(task)) {\n managedWorker.langs.add(lang);\n }\n try {\n // postMessage clones the request now, so keep the matching cache key on\n // the task instead of reading the caller's mutable target on response.\n if (task.type === 'file') {\n task.cacheKeyAtDispatch = task.request.file.cacheKey;\n } else if (task.type === 'diff') {\n task.cacheKeyAtDispatch = task.request.diff.cacheKey;\n }\n managedWorker.worker.postMessage(task.request);\n } catch (error) {\n console.error('Failed to post message to worker:', error);\n if (isRenderTask(task)) {\n this.notifyHighlightError(task, error);\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(error));\n } else if ('reject' in task) {\n task.reject(error as Error);\n }\n this.cleanWorkerAndTask(managedWorker, task);\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n this.queueBroadcastStateChanges();\n }\n\n private maybeAttachCustomExtensions(\n managedWorker: ManagedWorker,\n request: InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest\n ): void {\n if (request.customExtensionsVersion != null) {\n return;\n }\n const version = getCustomExtensionsVersion();\n if (managedWorker.customExtensionsVersion >= version) {\n return;\n }\n request.customExtensionsVersion = version;\n request.customExtensionMap = getCustomExtensionsMap();\n }\n\n private syncCustomExtensionVersion(\n managedWorker: ManagedWorker,\n request: InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest\n ): void {\n if (request.customExtensionsVersion == null) {\n return;\n }\n managedWorker.customExtensionsVersion = request.customExtensionsVersion;\n }\n\n private getAvailableWorker(\n langs: SupportedLanguages[]\n ): ManagedWorker | undefined {\n let worker: ManagedWorker | undefined;\n for (const managedWorker of this.workers) {\n if (\n managedWorker.requestId != null ||\n managedWorker.pendingSetupRequestId != null ||\n !managedWorker.initialized\n ) {\n continue;\n }\n worker = managedWorker;\n if (langs.length === 0) {\n break;\n }\n let hasEveryLang = true;\n for (const lang of langs) {\n if (!managedWorker.langs.has(lang)) {\n hasEveryLang = false;\n break;\n }\n }\n if (hasEveryLang) {\n break;\n }\n }\n return worker;\n }\n\n private getFileHighlightKey(file: FileContents): string | undefined {\n if (file.cacheKey == null) {\n return undefined;\n }\n return `file:${file.cacheKey}:${this.renderOptionsVersion}`;\n }\n\n private getDiffHighlightKey(diff: FileDiffMetadata): string | undefined {\n if (diff.cacheKey == null) {\n return undefined;\n }\n return `diff:${diff.cacheKey}:${this.renderOptionsVersion}`;\n }\n\n private getHighlightKeyForRequest(\n request: SubmitRequest\n ): string | undefined {\n switch (request.type) {\n case 'file':\n return this.getFileHighlightKey(request.file);\n case 'diff':\n return this.getDiffHighlightKey(request.diff);\n }\n }\n\n private hasActiveRequest(task: RenderTask): boolean {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.has(instance)) {\n return true;\n }\n }\n return false;\n }\n\n private addInstanceToTask(\n task: RenderTask,\n instance: FileRendererInstance | DiffRendererInstance\n ): void {\n if (task.type === 'file') {\n task.instances.add(instance as FileRendererInstance);\n } else {\n task.instances.add(instance as DiffRendererInstance);\n }\n if (this.activeTaskById.has(task.id)) {\n this.activeRequestByInstance.set(instance, task.id);\n } else {\n this.queuedTaskByInstance.set(instance, task);\n }\n }\n\n private detachInstanceFromQueuedTasks(\n instance: RenderTaskInstance,\n exceptTask?: RenderTask\n ): void {\n const task = this.queuedTaskByInstance.get(instance);\n if (task == null || task === exceptTask) {\n return;\n }\n this.queuedTaskByInstance.delete(instance);\n this.detachInstanceFromRenderTask(task, instance);\n if (!task.primeCache && task.instances.size === 0) {\n this.removeQueuedTask(task);\n }\n }\n\n private detachInstanceFromRenderTask(\n task: RenderTask,\n instance: RenderTaskInstance\n ): void {\n if (task.type === 'file') {\n task.instances.delete(instance as FileRendererInstance);\n } else {\n task.instances.delete(instance as DiffRendererInstance);\n }\n }\n\n private removeQueuedTask(task: RenderTask): void {\n const index = this.queuedTasks.indexOf(task);\n if (index !== -1) {\n this.queuedTasks.splice(index, 1);\n }\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearQueuedInstanceRequests(task);\n this.clearHighlightKey(task);\n }\n\n private removeActiveTask(task: RenderTask): void {\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearInstanceRequests(task);\n this.clearHighlightKey(task);\n this.activeTaskById.delete(task.id);\n }\n\n private createRenderTaskCallbacks(task: RenderTask): Promise<void> {\n return new Promise((resolve, reject) => {\n task.callbacks.add({ resolve, reject });\n });\n }\n\n private resolveRenderTaskCallbacks(task: RenderTask): void {\n for (const callbacks of task.callbacks) {\n callbacks.resolve();\n }\n task.callbacks.clear();\n }\n\n private rejectRenderTaskCallbacks(task: RenderTask, error: Error): void {\n for (const callbacks of task.callbacks) {\n callbacks.reject(error);\n }\n task.callbacks.clear();\n }\n\n private invalidateRenderTasks(): void {\n for (let index = this.queuedTasks.length - 1; index >= 0; index--) {\n const task = this.queuedTasks[index];\n if (task.renderOptionsVersion !== this.renderOptionsVersion) {\n this.removeQueuedTask(task);\n }\n }\n\n for (const task of Array.from(this.activeTaskById.values())) {\n if (\n isRenderTask(task) &&\n task.renderOptionsVersion !== this.renderOptionsVersion\n ) {\n this.removeActiveTask(task);\n }\n }\n }\n\n private clearQueuedInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n if (this.queuedTaskByInstance.get(instance) === task) {\n this.queuedTaskByInstance.delete(instance);\n }\n }\n }\n\n private clearHighlightKey(task: RenderTask): void {\n if (\n task.highlightKey != null &&\n this.taskByHighlightKey.get(task.highlightKey) === task\n ) {\n this.taskByHighlightKey.delete(task.highlightKey);\n }\n }\n\n private trackInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n this.activeRequestByInstance.set(instance, task.id);\n }\n }\n\n private clearInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n this.activeRequestByInstance.delete(instance);\n }\n }\n }\n\n private notifyFileInstances(\n task: RenderFileTask,\n result: ThemedFileResult,\n options: RenderFileOptions\n ): void {\n for (const instance of task.instances) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightSuccess(task.request.file, result, options);\n }\n }\n }\n\n private notifyDiffInstances(\n task: RenderDiffTask,\n result: ThemedDiffResult,\n options: RenderDiffOptions\n ): void {\n for (const instance of task.instances) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightSuccess(task.request.diff, result, options);\n }\n }\n }\n\n private notifyHighlightError(task: RenderTask, error: unknown): void {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightError(error);\n }\n }\n }\n\n private hasMatchingFileInstanceTask(\n instance: FileRendererInstance,\n file: FileContents\n ): boolean {\n for (const task of this.iterateRenderTasks()) {\n if (\n task.type === 'file' &&\n this.isCurrentRenderTask(task) &&\n task.instances.has(instance) &&\n areFilesEqual(file, task.request.file)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private hasMatchingDiffInstanceTask(\n instance: DiffRendererInstance,\n diff: FileDiffMetadata\n ): boolean {\n for (const task of this.iterateRenderTasks()) {\n if (\n task.type === 'diff' &&\n this.isCurrentRenderTask(task) &&\n task.instances.has(instance) &&\n areDiffTargetsEqual(task.request.diff, diff)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private getTaskByHighlightKey(highlightKey: string): RenderTask | undefined {\n const task = this.taskByHighlightKey.get(highlightKey);\n return task != null && this.isCurrentRenderTask(task) ? task : undefined;\n }\n\n private isCurrentRenderTask(task: RenderTask): boolean {\n return task.renderOptionsVersion === this.renderOptionsVersion;\n }\n\n private *iterateRenderTasks(): Generator<RenderTask> {\n for (const task of this.queuedTasks) {\n yield task;\n }\n for (const task of this.activeTaskById.values()) {\n if (isRenderTask(task)) {\n yield task;\n }\n }\n }\n\n private generateRequestId(): WorkerRequestId {\n return `req_${++this.nextRequestId}`;\n }\n}\n\nfunction shouldSyncCustomExtensions(\n request: AllWorkerTasks['request']\n): request is InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest {\n return (\n request.type === 'initialize' ||\n request.type === 'file' ||\n request.type === 'diff'\n );\n}\n\nfunction getLangsFromTask(task: AllWorkerTasks): SupportedLanguages[] {\n const langs = new Set<SupportedLanguages>();\n if (task.type === 'initialize' || task.type === 'set-render-options') {\n return [];\n }\n switch (task.type) {\n case 'file': {\n langs.add(\n task.request.file.lang ??\n getFiletypeFromFileName(task.request.file.name)\n );\n break;\n }\n case 'diff': {\n langs.add(\n task.request.diff.lang ??\n getFiletypeFromFileName(task.request.diff.name)\n );\n langs.add(\n task.request.diff.lang ??\n getFiletypeFromFileName(task.request.diff.prevName ?? '-')\n );\n break;\n }\n }\n langs.delete('text');\n return Array.from(langs);\n}\n\nfunction isRenderTask(task: AllWorkerTasks | undefined): task is RenderTask {\n return task?.type === 'file' || task?.type === 'diff';\n}\n\nfunction getInstances(\n task: RenderTask\n): Set<FileRendererInstance | DiffRendererInstance> {\n return task.instances as Set<FileRendererInstance | DiffRendererInstance>;\n}\n\nfunction normalizeWorkerError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkerPoolManager.js","names":[],"sources":["../../src/worker/WorkerPoolManager.ts"],"sourcesContent":["import LRUMapPkg from 'lru_map';\n\nimport { DEFAULT_THEMES } from '../constants';\nimport { getResolvedLanguages } from '../highlighter/languages/getResolvedLanguages';\nimport { hasResolvedLanguages } from '../highlighter/languages/hasResolvedLanguages';\nimport { resolveLanguages } from '../highlighter/languages/resolveLanguages';\nimport { getSharedHighlighter } from '../highlighter/shared_highlighter';\nimport { attachResolvedThemes } from '../highlighter/themes/attachResolvedThemes';\nimport { getResolvedThemes } from '../highlighter/themes/getResolvedThemes';\nimport { hasResolvedThemes } from '../highlighter/themes/hasResolvedThemes';\nimport { resolveThemes } from '../highlighter/themes/resolveThemes';\nimport type {\n DiffsHighlighter,\n FileContents,\n FileDiffMetadata,\n HighlighterTypes,\n HunkExpansionRegion,\n RenderDiffOptions,\n RenderDiffResult,\n RenderFileOptions,\n RenderFileResult,\n SupportedLanguages,\n ThemedDiffResult,\n ThemedFileResult,\n ThemeRegistrationResolved,\n} from '../types';\nimport { areDiffRenderOptionsEqual } from '../utils/areDiffRenderOptionsEqual';\nimport { areDiffTargetsEqual } from '../utils/areDiffTargetsEqual';\nimport { areFileRenderOptionsEqual } from '../utils/areFileRenderOptionsEqual';\nimport { areFilesEqual } from '../utils/areFilesEqual';\nimport { areThemesEqual } from '../utils/areThemesEqual';\nimport {\n getCustomExtensionsMap,\n getCustomExtensionsVersion,\n getFiletypeFromFileName,\n} from '../utils/getFiletypeFromFileName';\nimport { getThemes } from '../utils/getThemes';\nimport { isDiffPlainText } from '../utils/isDiffPlainText';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { renderDiffWithHighlighter } from '../utils/renderDiffWithHighlighter';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport type {\n AllWorkerTasks,\n DiffRendererInstance,\n FileRendererInstance,\n InitializeWorkerRequest,\n InitializeWorkerTask,\n RenderDiffRequest,\n RenderDiffTask,\n RenderFileRequest,\n RenderFileTask,\n ResolvedLanguage,\n SetRenderOptionsWorkerTask,\n SubmitRequest,\n WorkerInitializationRenderOptions,\n WorkerPoolOptions,\n WorkerRenderingOptions,\n WorkerRequestId,\n WorkerResponse,\n WorkerStats,\n} from './types';\n\nconst IGNORE_RESPONSE = Symbol('IGNORE_RESPONSE');\n\nclass WorkerPoolTerminatedError extends Error {\n constructor() {\n super('WorkerPoolManager: operation canceled because the pool terminated');\n }\n}\n\nclass WorkerPoolTaskCanceledError extends Error {\n constructor() {\n super('WorkerPoolManager: operation canceled before the task completed');\n }\n}\n\ninterface GetCachesResult {\n fileCache: LRUMapPkg.LRUMap<string, RenderFileResult>;\n diffCache: LRUMapPkg.LRUMap<string, RenderDiffResult>;\n}\n\ninterface ManagedWorker {\n worker: Worker;\n requestId: string | undefined;\n pendingSetupRequestId: WorkerRequestId | undefined;\n initialized: boolean;\n langs: Set<SupportedLanguages>;\n customExtensionsVersion: number;\n}\n\ninterface ThemeSubscriber {\n onThemeChange(): void;\n}\n\ntype RenderTask = RenderFileTask | RenderDiffTask;\n\ntype RenderTaskInstance = FileRendererInstance | DiffRendererInstance;\n\nexport class WorkerPoolManager {\n private highlighter: DiffsHighlighter | undefined;\n private readonly preferredHighlighter: HighlighterTypes;\n private renderOptions: WorkerRenderingOptions;\n private renderOptionsRequestVersion = 0;\n private renderOptionsVersion = 0;\n private initialized: Promise<void> | boolean = false;\n private workers: ManagedWorker[] = [];\n // Tasks that are waiting to get processed by a worker\n private queuedTasks: RenderTask[] = [];\n private queuedTaskByInstance = new Map<RenderTaskInstance, RenderTask>();\n\n // Tasks that map to highlightKey are essentially singular, so we only\n // need one map to include queued and active\n private taskByHighlightKey = new Map<string, RenderTask>();\n\n // Tasks that have already been sent to a worker and are awaiting a response.\n private activeTaskById = new Map<WorkerRequestId, AllWorkerTasks>();\n private activeRequestByInstance = new Map<\n RenderTaskInstance,\n WorkerRequestId\n >();\n\n private nextRequestId = 0;\n private themeSubscribers = new Set<ThemeSubscriber>();\n private workersFailed = false;\n private statSubscribers = new Set<(stats: WorkerStats) => unknown>();\n private fileCache: LRUMapPkg.LRUMap<string, RenderFileResult>;\n private diffCache: LRUMapPkg.LRUMap<string, RenderDiffResult>;\n private _queuedBroadcast: number | undefined;\n // Incremented on terminate so async lifecycle work can identify stale results.\n private lifecycleGeneration = 0;\n\n constructor(\n private options: WorkerPoolOptions,\n {\n langs,\n theme = DEFAULT_THEMES,\n useTokenTransformer = false,\n lineDiffType = 'word-alt',\n maxLineDiffLength = 1000,\n tokenizeMaxLineLength = 1000,\n preferredHighlighter = 'shiki-js',\n }: WorkerInitializationRenderOptions\n ) {\n this.preferredHighlighter = preferredHighlighter;\n this.renderOptions = {\n theme,\n useTokenTransformer,\n lineDiffType,\n maxLineDiffLength,\n tokenizeMaxLineLength,\n };\n this.fileCache = new LRUMapPkg.LRUMap(options.totalASTLRUCacheSize ?? 100);\n this.diffCache = new LRUMapPkg.LRUMap(options.totalASTLRUCacheSize ?? 100);\n this.queueInitialization(langs);\n }\n\n public isWorkingPool(): boolean {\n return !this.workersFailed;\n }\n\n public getFileResultCache(file: FileContents): RenderFileResult | undefined {\n return file.cacheKey != null\n ? this.fileCache.get(file.cacheKey)\n : undefined;\n }\n\n public getDiffResultCache(\n diff: FileDiffMetadata\n ): RenderDiffResult | undefined {\n return diff.cacheKey != null\n ? this.diffCache.get(diff.cacheKey)\n : undefined;\n }\n\n public inspectCaches(): GetCachesResult {\n const { fileCache, diffCache } = this;\n return { fileCache, diffCache };\n }\n\n public evictFileFromCache(cacheKey: string): boolean {\n try {\n return this.fileCache.delete(cacheKey) !== undefined;\n } finally {\n this.queueBroadcastStateChanges();\n }\n }\n\n public evictDiffFromCache(cacheKey: string): boolean {\n try {\n return this.diffCache.delete(cacheKey) !== undefined;\n } finally {\n this.queueBroadcastStateChanges();\n }\n }\n\n async setRenderOptions({\n theme = this.renderOptions.theme ?? DEFAULT_THEMES,\n useTokenTransformer = this.renderOptions.useTokenTransformer ?? false,\n lineDiffType = this.renderOptions.lineDiffType ?? 'word-alt',\n maxLineDiffLength = this.renderOptions.maxLineDiffLength ?? 1000,\n tokenizeMaxLineLength = this.renderOptions.tokenizeMaxLineLength ?? 1000,\n }: Partial<WorkerRenderingOptions>): Promise<void> {\n const { lifecycleGeneration } = this;\n const renderOptionsRequestVersion = ++this.renderOptionsRequestVersion;\n const isCurrentRequest = (): boolean =>\n this.isCurrentLifecycle(lifecycleGeneration) &&\n this.renderOptionsRequestVersion === renderOptionsRequestVersion;\n try {\n const newRenderOptions: WorkerRenderingOptions = {\n theme,\n useTokenTransformer,\n lineDiffType,\n maxLineDiffLength,\n tokenizeMaxLineLength,\n };\n if (!this.isInitialized()) {\n await this.initialize();\n }\n if (\n !isCurrentRequest() ||\n areDiffRenderOptionsEqual(newRenderOptions, this.renderOptions)\n ) {\n return;\n }\n\n const themeNames = getThemes(theme);\n let resolvedThemes: ThemeRegistrationResolved[] = [];\n if (!areThemesEqual(newRenderOptions.theme, this.renderOptions.theme)) {\n if (hasResolvedThemes(themeNames)) {\n resolvedThemes = getResolvedThemes(themeNames);\n } else {\n resolvedThemes = await resolveThemes(themeNames);\n }\n }\n\n if (!isCurrentRequest()) {\n return;\n }\n\n if (this.highlighter != null) {\n attachResolvedThemes(resolvedThemes, this.highlighter);\n } else {\n const highlighter = await getSharedHighlighter({\n themes: themeNames,\n langs: ['text'],\n preferredHighlighter: this.preferredHighlighter,\n });\n if (!isCurrentRequest()) {\n return;\n }\n this.highlighter = highlighter;\n }\n\n const workerSetup = this.setRenderOptionsOnWorkers(\n newRenderOptions,\n resolvedThemes\n );\n\n this.renderOptions = newRenderOptions;\n this.renderOptionsVersion++;\n this.diffCache.clear();\n this.fileCache.clear();\n this.invalidateRenderTasks();\n\n for (const instance of this.themeSubscribers) {\n instance.onThemeChange();\n }\n\n await workerSetup;\n } catch (error) {\n if (error instanceof WorkerPoolTerminatedError || !isCurrentRequest()) {\n return;\n }\n throw error;\n }\n }\n\n public getPreferredHighlighter(): HighlighterTypes {\n return this.preferredHighlighter;\n }\n\n public getFileRenderOptions(): RenderFileOptions {\n const { tokenizeMaxLineLength, theme, useTokenTransformer } =\n this.renderOptions;\n return { theme, useTokenTransformer, tokenizeMaxLineLength };\n }\n\n public getDiffRenderOptions(): RenderDiffOptions {\n return { ...this.renderOptions };\n }\n\n private async setRenderOptionsOnWorkers(\n renderOptions: WorkerRenderingOptions,\n resolvedThemes: ThemeRegistrationResolved[]\n ): Promise<void> {\n if (this.workersFailed) {\n return;\n }\n if (!this.isInitialized()) {\n await this.initialize();\n }\n const taskPromises: Promise<void>[] = [];\n for (const managedWorker of this.workers) {\n if (!managedWorker.initialized) {\n console.log({ managedWorker });\n throw new Error(\n 'setRenderOptionsOnWorkers: Somehow we have an uninitialized worker'\n );\n }\n taskPromises.push(\n new Promise<void>((resolve, reject) => {\n const id = this.generateRequestId();\n const task: SetRenderOptionsWorkerTask = {\n type: 'set-render-options',\n id,\n request: {\n type: 'set-render-options',\n id,\n renderOptions,\n resolvedThemes,\n },\n resolve,\n reject,\n requestStart: Date.now(),\n };\n // Render-option updates are posted immediately, but the worker stays\n // unavailable for new render work until it acknowledges this message.\n this.activeTaskById.set(id, task);\n managedWorker.pendingSetupRequestId = id;\n managedWorker.worker.postMessage(task.request);\n })\n );\n }\n await Promise.all(taskPromises);\n }\n\n public subscribeToThemeChanges(instance: ThemeSubscriber): () => void {\n this.themeSubscribers.add(instance);\n this.queueBroadcastStateChanges();\n return () => {\n this.unsubscribeToThemeChanges(instance);\n this.queueBroadcastStateChanges();\n };\n }\n\n public unsubscribeToThemeChanges(instance: ThemeSubscriber): void {\n this.themeSubscribers.delete(instance);\n this.queueBroadcastStateChanges();\n }\n\n public subscribeToStatChanges(\n callback: (stats: WorkerStats) => unknown\n ): () => void {\n this.statSubscribers.add(callback);\n callback(this.getStats());\n return () => {\n this.statSubscribers.delete(callback);\n };\n }\n\n private queueBroadcastStateChanges() {\n if (this._queuedBroadcast != null) return;\n this._queuedBroadcast = requestAnimationFrame(this._broadcastStateChanges);\n }\n\n private _broadcastStateChanges = () => {\n if (this._queuedBroadcast != null) {\n cancelAnimationFrame(this._queuedBroadcast);\n this._queuedBroadcast = undefined;\n }\n const stats = this.getStats();\n for (const callback of this.statSubscribers) {\n callback(stats);\n }\n };\n\n public cleanUpTasks(instance: RenderTaskInstance): void {\n this.detachInstanceFromQueuedTasks(instance);\n const requestId = this.activeRequestByInstance.get(instance);\n if (requestId != null) {\n const task = this.activeTaskById.get(requestId);\n if (isRenderTask(task)) {\n this.detachInstanceFromRenderTask(task, instance);\n if (!task.primeCache && task.instances.size === 0) {\n this.removeActiveTask(task);\n }\n } else {\n this.activeTaskById.delete(requestId);\n }\n }\n this.activeRequestByInstance.delete(instance);\n this.queueBroadcastStateChanges();\n }\n\n public isInitialized(): boolean {\n return this.initialized === true;\n }\n\n public async initialize(languages: SupportedLanguages[] = []): Promise<void> {\n if (this.initialized === true) {\n return;\n } else if (this.initialized === false) {\n const { lifecycleGeneration } = this;\n this.initialized = new Promise((resolve, reject) => {\n void (async () => {\n try {\n const themes = getThemes(this.renderOptions.theme);\n let resolvedThemes: ThemeRegistrationResolved[] = [];\n if (hasResolvedThemes(themes)) {\n resolvedThemes = getResolvedThemes(themes);\n } else {\n resolvedThemes = await resolveThemes(themes);\n }\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n resolve();\n return;\n }\n\n let resolvedLanguages: ResolvedLanguage[] = [];\n if (hasResolvedLanguages(languages)) {\n resolvedLanguages = getResolvedLanguages(languages);\n } else {\n resolvedLanguages = await resolveLanguages(languages);\n }\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n resolve();\n return;\n }\n\n const [highlighter] = await Promise.all([\n getSharedHighlighter({\n themes,\n langs: ['text', ...languages],\n preferredHighlighter: this.preferredHighlighter,\n }),\n this.initializeWorkers(resolvedThemes, resolvedLanguages),\n ]);\n\n if (!this.isCurrentLifecycle(lifecycleGeneration)) {\n this.terminateWorkers();\n resolve();\n return;\n }\n this.highlighter = highlighter;\n this.initialized = true;\n this.diffCache.clear();\n this.fileCache.clear();\n this.drainQueue();\n this.queueBroadcastStateChanges();\n resolve();\n } catch (e) {\n if (\n e instanceof WorkerPoolTerminatedError ||\n !this.isCurrentLifecycle(lifecycleGeneration)\n ) {\n resolve();\n return;\n }\n this.initialized = false;\n this.workersFailed = true;\n for (const task of this.queuedTasks) {\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(e));\n }\n this.queueBroadcastStateChanges();\n reject(e);\n }\n })();\n });\n this.queueBroadcastStateChanges();\n } else {\n return this.initialized;\n }\n }\n\n private async initializeWorkers(\n resolvedThemes: ThemeRegistrationResolved[],\n resolvedLanguages: ResolvedLanguage[]\n ): Promise<void> {\n this.workersFailed = false;\n const initPromises: Promise<unknown>[] = [];\n const customExtensionVersion = getCustomExtensionsVersion();\n const customExtensionMap =\n customExtensionVersion > 0 ? getCustomExtensionsMap() : undefined;\n if (this.workers.length > 0) {\n this.terminateWorkers();\n }\n for (let i = 0; i < (this.options.poolSize ?? 8); i++) {\n const worker = this.options.workerFactory();\n const managedWorker: ManagedWorker = {\n worker,\n requestId: undefined,\n pendingSetupRequestId: undefined,\n initialized: false,\n langs: new Set(['text', ...resolvedLanguages.map(({ name }) => name)]),\n customExtensionsVersion: 0,\n };\n worker.addEventListener(\n 'message',\n (event: MessageEvent<WorkerResponse>) => {\n this.handleWorkerMessage(managedWorker, event.data);\n }\n );\n worker.addEventListener('error', (error) =>\n console.error('Worker error:', error, managedWorker)\n );\n this.workers.push(managedWorker);\n initPromises.push(\n new Promise<void>((resolve, reject) => {\n const id = this.generateRequestId();\n const task: InitializeWorkerTask = {\n type: 'initialize',\n id,\n request: {\n type: 'initialize',\n id,\n renderOptions: this.renderOptions,\n preferredHighlighter: this.preferredHighlighter,\n resolvedThemes,\n resolvedLanguages,\n customExtensionsVersion:\n customExtensionMap != null ? customExtensionVersion : undefined,\n customExtensionMap,\n },\n resolve() {\n managedWorker.initialized = true;\n resolve();\n },\n reject,\n requestStart: Date.now(),\n };\n this.activeTaskById.set(id, task);\n this.executeTask(managedWorker, task);\n })\n );\n }\n await Promise.all(initPromises);\n }\n\n private drainQueue = () => {\n this._queuedDrain = undefined;\n // If we are initializing or things got cancelled while initializing, we\n // should not attempt to drain the queue\n if (this.initialized !== true || this.queuedTasks.length === 0) {\n return;\n }\n for (let i = 0; i < this.queuedTasks.length; ) {\n const task = this.queuedTasks[i];\n // If any instance has a request in progress, we should wait for it to\n // finish before starting work that would notify that instance.\n if (this.hasActiveRequest(task)) {\n i++;\n continue;\n }\n const langs = getLangsFromTask(task);\n const availableWorker = this.getAvailableWorker(langs);\n if (availableWorker == null) {\n break;\n }\n this.queuedTasks.splice(i, 1);\n this.assignWorkerToTask(task, availableWorker);\n void this.resolveLanguagesAndExecuteTask(availableWorker, task, langs);\n }\n this.queueBroadcastStateChanges();\n };\n\n public highlightFileAST(\n instance: FileRendererInstance,\n file: FileContents\n ): void {\n const cachedResult = this.getFileResultCache(file);\n // If we've already highlighted the file or it's plain text, we should not\n // attempt to highlight. This should be mostly never hit, but it's just an\n // extra level of safety\n if (\n isFilePlainText(file) ||\n (cachedResult != null &&\n areFileRenderOptionsEqual(\n cachedResult.options,\n this.getFileRenderOptions()\n ))\n ) {\n return;\n }\n if (!this.hasMatchingFileInstanceTask(instance, file)) {\n this.submitTask(instance, { type: 'file', file });\n }\n }\n\n public primeFileHighlightCache(file: FileContents): Promise<void> {\n if (!this.isWorkingPool()) {\n return Promise.reject(\n new Error(\n 'WorkerPoolManager.primeFileHighlightCache: worker pool is not working'\n )\n );\n }\n\n const task = this.getOrCreateFileHighlightCacheTask(file);\n return task != null\n ? this.createRenderTaskCallbacks(task)\n : Promise.resolve();\n }\n\n private getOrCreateFileHighlightCacheTask(\n file: FileContents\n ): RenderFileTask | undefined {\n if (file.cacheKey == null) {\n console.warn(\n `WorkerPoolManager.primeFileHighlightCache: priming highlight cache requires file.cacheKey; skipping \"${file.name}\".`\n );\n return undefined;\n }\n const cachedResult = this.getFileResultCache(file);\n const highlightKey = this.getFileHighlightKey(file);\n if (\n highlightKey == null ||\n isFilePlainText(file) ||\n (cachedResult != null &&\n areFileRenderOptionsEqual(\n cachedResult.options,\n this.getFileRenderOptions()\n ))\n ) {\n return undefined;\n }\n const existingTask = this.getTaskByHighlightKey(highlightKey);\n if (existingTask != null) {\n existingTask.primeCache = true;\n return existingTask.type === 'file' ? existingTask : undefined;\n } else {\n const task = this.submitCacheTask({ type: 'file', file }, highlightKey);\n return task.type === 'file' ? task : undefined;\n }\n }\n\n public getPlainFileAST(\n file: FileContents,\n startingLine: number,\n totalLines: number,\n lines?: string[]\n ): ThemedFileResult | undefined {\n if (this.highlighter == null) {\n this.queueInitialization();\n return undefined;\n }\n return renderFileWithHighlighter(\n file,\n this.highlighter,\n this.renderOptions,\n { forcePlainText: true, startingLine, totalLines, lines }\n );\n }\n\n public highlightDiffAST(\n instance: DiffRendererInstance,\n diff: FileDiffMetadata\n ): void {\n const cachedResult = this.getDiffResultCache(diff);\n // If we've already highlighted the diff or it's plain text, we should not\n // attempt to highlight. This should be mostly never hit, but it's just an\n // extra level of safety\n if (\n isDiffPlainText(diff) ||\n (cachedResult != null &&\n areDiffRenderOptionsEqual(\n cachedResult.options,\n this.getDiffRenderOptions()\n ))\n ) {\n return;\n }\n if (!this.hasMatchingDiffInstanceTask(instance, diff)) {\n this.submitTask(instance, { type: 'diff', diff });\n }\n }\n\n public primeDiffHighlightCache(diff: FileDiffMetadata): Promise<void> {\n if (!this.isWorkingPool()) {\n return Promise.reject(\n new Error(\n 'WorkerPoolManager.primeDiffHighlightCache: worker pool is not working'\n )\n );\n }\n\n const task = this.getOrCreateDiffHighlightCacheTask(diff);\n return task != null\n ? this.createRenderTaskCallbacks(task)\n : Promise.resolve();\n }\n\n private getOrCreateDiffHighlightCacheTask(\n diff: FileDiffMetadata\n ): RenderDiffTask | undefined {\n if (diff.cacheKey == null) {\n console.warn(\n `WorkerPoolManager.primeDiffHighlightCache: priming highlight cache requires diff.cacheKey; skipping \"${diff.prevName ?? diff.name}\" -> \"${diff.name}\".`\n );\n return undefined;\n }\n const cachedResult = this.getDiffResultCache(diff);\n const highlightKey = this.getDiffHighlightKey(diff);\n if (\n highlightKey == null ||\n isDiffPlainText(diff) ||\n (cachedResult != null &&\n areDiffRenderOptionsEqual(\n cachedResult.options,\n this.getDiffRenderOptions()\n ))\n ) {\n return undefined;\n }\n const existingTask = this.getTaskByHighlightKey(highlightKey);\n if (existingTask != null) {\n existingTask.primeCache = true;\n return existingTask.type === 'diff' ? existingTask : undefined;\n } else {\n const task = this.submitCacheTask({ type: 'diff', diff }, highlightKey);\n return task.type === 'diff' ? task : undefined;\n }\n }\n\n public getPlainDiffAST(\n diff: FileDiffMetadata,\n startingLine: number,\n totalLines: number,\n expandedHunks?: Map<number, HunkExpansionRegion> | true,\n collapsedContextThreshold?: number\n ): ThemedDiffResult | undefined {\n return this.highlighter != null\n ? renderDiffWithHighlighter(diff, this.highlighter, this.renderOptions, {\n forcePlainText: true,\n startingLine,\n totalLines,\n expandedHunks,\n collapsedContextThreshold,\n })\n : undefined;\n }\n\n public terminate(): void {\n this.lifecycleGeneration++;\n this.cancelActiveWorkerTasks();\n this.terminateWorkers();\n const error = new WorkerPoolTerminatedError();\n for (const task of this.queuedTasks) {\n this.rejectRenderTaskCallbacks(task, error);\n }\n this.fileCache.clear();\n this.diffCache.clear();\n this.activeRequestByInstance.clear();\n this.queuedTasks.length = 0;\n this.queuedTaskByInstance.clear();\n this.taskByHighlightKey.clear();\n this.activeTaskById.clear();\n this.highlighter = undefined;\n this.initialized = false;\n this.workersFailed = false;\n this.queueBroadcastStateChanges();\n }\n\n private isCurrentLifecycle(lifecycleGeneration: number): boolean {\n return this.lifecycleGeneration === lifecycleGeneration;\n }\n\n private queueInitialization(languages?: SupportedLanguages[]): void {\n void this.initialize(languages).catch((error) => {\n console.error(error);\n });\n }\n\n private cancelActiveWorkerTasks(): void {\n const error = new WorkerPoolTerminatedError();\n for (const task of this.activeTaskById.values()) {\n if ('reject' in task) {\n task.reject(error);\n } else if (isRenderTask(task)) {\n this.rejectRenderTaskCallbacks(task, error);\n }\n }\n }\n\n private terminateWorkers() {\n for (const managedWorker of this.workers) {\n managedWorker.worker.terminate();\n }\n this.workers.length = 0;\n }\n\n public getStats(): WorkerStats {\n return {\n managerState: (() => {\n if (this.initialized === false) {\n return 'waiting';\n }\n if (this.initialized !== true) {\n return 'initializing';\n }\n return 'initialized';\n })(),\n totalWorkers: this.workers.length,\n workersFailed: this.workersFailed,\n busyWorkers: this.workers.filter(\n (w) => w.requestId != null || w.pendingSetupRequestId != null\n ).length,\n queuedTasks: this.queuedTasks.length,\n activeTasks: this.activeTaskById.size,\n themeSubscribers: this.themeSubscribers.size,\n fileCacheSize: this.fileCache.size,\n diffCacheSize: this.diffCache.size,\n };\n }\n\n private submitTask(\n instance: FileRendererInstance,\n request: Omit<RenderFileRequest, 'id'>\n ): void;\n private submitTask(\n instance: DiffRendererInstance,\n request: Omit<RenderDiffRequest, 'id'>\n ): void;\n private submitTask(\n instance: FileRendererInstance | DiffRendererInstance,\n request: SubmitRequest\n ): void {\n if (this.initialized === false) {\n this.queueInitialization();\n }\n\n const highlightKey = this.getHighlightKeyForRequest(request);\n const existingTask =\n highlightKey != null\n ? this.getTaskByHighlightKey(highlightKey)\n : undefined;\n if (existingTask != null) {\n this.detachInstanceFromQueuedTasks(instance, existingTask);\n this.addInstanceToTask(existingTask, instance);\n this.queueBroadcastStateChanges();\n return;\n }\n\n this.detachInstanceFromQueuedTasks(instance);\n const id = this.generateRequestId();\n const requestStart = Date.now();\n const { renderOptionsVersion } = this;\n const task: RenderTask = (() => {\n switch (request.type) {\n case 'file':\n return {\n type: 'file',\n id,\n request: { ...request, id },\n instances: new Set([instance as FileRendererInstance]),\n primeCache: false,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n case 'diff':\n return {\n type: 'diff',\n id,\n request: { ...request, id },\n instances: new Set([instance as DiffRendererInstance]),\n primeCache: false,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n }\n })();\n this.enqueueRenderTask(task, instance);\n }\n\n private submitCacheTask(\n request: SubmitRequest,\n highlightKey: string\n ): RenderTask {\n if (this.initialized === false) {\n this.queueInitialization();\n }\n const id = this.generateRequestId();\n const requestStart = Date.now();\n const { renderOptionsVersion } = this;\n const task: RenderTask = (() => {\n switch (request.type) {\n case 'file':\n return {\n type: 'file',\n id,\n request: { ...request, id },\n instances: new Set<FileRendererInstance>(),\n primeCache: true,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n case 'diff':\n return {\n type: 'diff',\n id,\n request: { ...request, id },\n instances: new Set<DiffRendererInstance>(),\n primeCache: true,\n highlightKey,\n callbacks: new Set(),\n renderOptionsVersion,\n requestStart,\n };\n }\n })();\n this.enqueueRenderTask(task);\n return task;\n }\n\n private enqueueRenderTask(\n task: RenderTask,\n instance?: RenderTaskInstance\n ): void {\n this.queuedTasks.push(task);\n if (instance != null) {\n this.queuedTaskByInstance.set(instance, task);\n }\n if (task.highlightKey != null) {\n this.taskByHighlightKey.set(task.highlightKey, task);\n }\n this.queueDrain();\n }\n\n private async resolveLanguagesAndExecuteTask(\n availableWorker: ManagedWorker,\n task: RenderFileTask | RenderDiffTask,\n langs: SupportedLanguages[]\n ): Promise<void> {\n try {\n // Add resolved languages if required\n const workerMissingLangs = langs.filter(\n (lang) => !availableWorker.langs.has(lang)\n );\n\n if (workerMissingLangs.length > 0) {\n if (hasResolvedLanguages(workerMissingLangs)) {\n task.request.resolvedLanguages =\n getResolvedLanguages(workerMissingLangs);\n } else {\n task.request.resolvedLanguages =\n await resolveLanguages(workerMissingLangs);\n }\n }\n // If the task has been cleaned up after awaiting language resolving,\n // lets fully clean it up\n if (!this.activeTaskById.has(task.id)) {\n if (availableWorker.requestId === task.id) {\n this.cleanWorkerAndTask(availableWorker, task);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n return;\n }\n this.executeTask(availableWorker, task);\n } catch (error) {\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(error));\n this.cleanWorkerAndTask(availableWorker, task);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n }\n\n private handleWorkerMessage(\n managedWorker: ManagedWorker,\n response: WorkerResponse\n ): void {\n const task = this.activeTaskById.get(response.id);\n try {\n if (task == null) {\n // If we can't find a task for this response, it probably means the\n // component has been unmounted, so we should silently ignore it\n throw IGNORE_RESPONSE;\n } else if (response.type === 'error') {\n const error = new Error(response.error);\n if (response.stack) {\n error.stack = response.stack;\n }\n if ('reject' in task) {\n task.reject(error);\n } else if (isRenderTask(task)) {\n this.notifyHighlightError(task, error);\n this.rejectRenderTaskCallbacks(task, error);\n } else {\n throw new Error('handleWorkerMessage: unknown task type');\n }\n throw error;\n } else {\n switch (response.requestType) {\n case 'initialize':\n if (task.type !== 'initialize') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n this.syncCustomExtensionVersion(managedWorker, task.request);\n task.resolve();\n break;\n case 'set-render-options':\n if (task.type !== 'set-render-options') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n task.resolve();\n break;\n case 'file': {\n if (task.type !== 'file') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n const { result, options } = response;\n if (\n !this.isCurrentRenderTask(task) ||\n !areFileRenderOptionsEqual(options, this.getFileRenderOptions())\n ) {\n throw IGNORE_RESPONSE;\n }\n const { request } = task;\n this.syncCustomExtensionVersion(managedWorker, request);\n if (task.cacheKeyAtDispatch != null) {\n this.fileCache.set(task.cacheKeyAtDispatch, { result, options });\n }\n this.resolveRenderTaskCallbacks(task);\n this.notifyFileInstances(task, result, options);\n break;\n }\n case 'diff': {\n if (task.type !== 'diff') {\n throw new Error('handleWorkerMessage: task/response dont match');\n }\n const { result, options } = response;\n if (\n !this.isCurrentRenderTask(task) ||\n !areDiffRenderOptionsEqual(options, this.getDiffRenderOptions())\n ) {\n throw IGNORE_RESPONSE;\n }\n const { request } = task;\n this.syncCustomExtensionVersion(managedWorker, request);\n if (task.cacheKeyAtDispatch != null) {\n this.diffCache.set(task.cacheKeyAtDispatch, { result, options });\n }\n this.resolveRenderTaskCallbacks(task);\n this.notifyDiffInstances(task, result, options);\n break;\n }\n }\n }\n } catch (error) {\n if (error !== IGNORE_RESPONSE) {\n console.error(error, task, response);\n }\n }\n\n this.cleanWorkerAndTask(managedWorker, task, response.id);\n this.queueBroadcastStateChanges();\n if (this.queuedTasks.length > 0) {\n // We queue drain so that potentially multiple workers can free up\n // allowing for better language matches if possible\n this.queueDrain();\n }\n }\n\n private _queuedDrain: Promise<void> | undefined;\n private queueDrain() {\n if (this._queuedDrain != null) return;\n this._queuedDrain = Promise.resolve().then(this.drainQueue);\n this.queueBroadcastStateChanges();\n }\n\n private assignWorkerToTask(\n task: AllWorkerTasks,\n managedWorker: ManagedWorker\n ) {\n managedWorker.requestId = task.id;\n if (isRenderTask(task)) {\n this.clearQueuedInstanceRequests(task);\n this.trackInstanceRequests(task);\n }\n this.activeTaskById.set(task.id, task);\n }\n\n private cleanWorkerAndTask(\n managedWorker: ManagedWorker,\n task?: AllWorkerTasks,\n requestId: WorkerRequestId | undefined = task?.id\n ) {\n if (managedWorker.requestId === requestId) {\n managedWorker.requestId = undefined;\n }\n if (managedWorker.pendingSetupRequestId === requestId) {\n managedWorker.pendingSetupRequestId = undefined;\n }\n if (task != null) {\n if (isRenderTask(task)) {\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearInstanceRequests(task);\n this.clearHighlightKey(task);\n }\n this.activeTaskById.delete(task.id);\n }\n }\n\n private executeTask(\n managedWorker: ManagedWorker,\n task: AllWorkerTasks\n ): void {\n if (shouldSyncCustomExtensions(task.request)) {\n this.maybeAttachCustomExtensions(managedWorker, task.request);\n }\n if (!this.activeTaskById.has(task.id)) {\n this.assignWorkerToTask(task, managedWorker);\n }\n for (const lang of getLangsFromTask(task)) {\n managedWorker.langs.add(lang);\n }\n try {\n // postMessage clones the request now, so keep the matching cache key on\n // the task instead of reading the caller's mutable target on response.\n if (task.type === 'file') {\n task.cacheKeyAtDispatch = task.request.file.cacheKey;\n } else if (task.type === 'diff') {\n task.cacheKeyAtDispatch = task.request.diff.cacheKey;\n }\n managedWorker.worker.postMessage(task.request);\n } catch (error) {\n console.error('Failed to post message to worker:', error);\n if (isRenderTask(task)) {\n this.notifyHighlightError(task, error);\n this.rejectRenderTaskCallbacks(task, normalizeWorkerError(error));\n } else if ('reject' in task) {\n task.reject(error as Error);\n }\n this.cleanWorkerAndTask(managedWorker, task);\n if (this.queuedTasks.length > 0) {\n this.queueDrain();\n }\n }\n this.queueBroadcastStateChanges();\n }\n\n private maybeAttachCustomExtensions(\n managedWorker: ManagedWorker,\n request: InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest\n ): void {\n if (request.customExtensionsVersion != null) {\n return;\n }\n const version = getCustomExtensionsVersion();\n if (managedWorker.customExtensionsVersion >= version) {\n return;\n }\n request.customExtensionsVersion = version;\n request.customExtensionMap = getCustomExtensionsMap();\n }\n\n private syncCustomExtensionVersion(\n managedWorker: ManagedWorker,\n request: InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest\n ): void {\n if (request.customExtensionsVersion == null) {\n return;\n }\n managedWorker.customExtensionsVersion = request.customExtensionsVersion;\n }\n\n private getAvailableWorker(\n langs: SupportedLanguages[]\n ): ManagedWorker | undefined {\n let worker: ManagedWorker | undefined;\n for (const managedWorker of this.workers) {\n if (\n managedWorker.requestId != null ||\n managedWorker.pendingSetupRequestId != null ||\n !managedWorker.initialized\n ) {\n continue;\n }\n worker = managedWorker;\n if (langs.length === 0) {\n break;\n }\n let hasEveryLang = true;\n for (const lang of langs) {\n if (!managedWorker.langs.has(lang)) {\n hasEveryLang = false;\n break;\n }\n }\n if (hasEveryLang) {\n break;\n }\n }\n return worker;\n }\n\n private getFileHighlightKey(file: FileContents): string | undefined {\n if (file.cacheKey == null) {\n return undefined;\n }\n return `file:${file.cacheKey}:${this.renderOptionsVersion}`;\n }\n\n private getDiffHighlightKey(diff: FileDiffMetadata): string | undefined {\n if (diff.cacheKey == null) {\n return undefined;\n }\n return `diff:${diff.cacheKey}:${this.renderOptionsVersion}`;\n }\n\n private getHighlightKeyForRequest(\n request: SubmitRequest\n ): string | undefined {\n switch (request.type) {\n case 'file':\n return this.getFileHighlightKey(request.file);\n case 'diff':\n return this.getDiffHighlightKey(request.diff);\n }\n }\n\n private hasActiveRequest(task: RenderTask): boolean {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.has(instance)) {\n return true;\n }\n }\n return false;\n }\n\n private addInstanceToTask(\n task: RenderTask,\n instance: FileRendererInstance | DiffRendererInstance\n ): void {\n if (task.type === 'file') {\n task.instances.add(instance as FileRendererInstance);\n } else {\n task.instances.add(instance as DiffRendererInstance);\n }\n if (this.activeTaskById.has(task.id)) {\n this.activeRequestByInstance.set(instance, task.id);\n } else {\n this.queuedTaskByInstance.set(instance, task);\n }\n }\n\n private detachInstanceFromQueuedTasks(\n instance: RenderTaskInstance,\n exceptTask?: RenderTask\n ): void {\n const task = this.queuedTaskByInstance.get(instance);\n if (task == null || task === exceptTask) {\n return;\n }\n this.queuedTaskByInstance.delete(instance);\n this.detachInstanceFromRenderTask(task, instance);\n if (!task.primeCache && task.instances.size === 0) {\n this.removeQueuedTask(task);\n }\n }\n\n private detachInstanceFromRenderTask(\n task: RenderTask,\n instance: RenderTaskInstance\n ): void {\n if (task.type === 'file') {\n task.instances.delete(instance as FileRendererInstance);\n } else {\n task.instances.delete(instance as DiffRendererInstance);\n }\n }\n\n private removeQueuedTask(task: RenderTask): void {\n const index = this.queuedTasks.indexOf(task);\n if (index !== -1) {\n this.queuedTasks.splice(index, 1);\n }\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearQueuedInstanceRequests(task);\n this.clearHighlightKey(task);\n }\n\n private removeActiveTask(task: RenderTask): void {\n this.rejectRenderTaskCallbacks(task, new WorkerPoolTaskCanceledError());\n this.clearInstanceRequests(task);\n this.clearHighlightKey(task);\n this.activeTaskById.delete(task.id);\n }\n\n private createRenderTaskCallbacks(task: RenderTask): Promise<void> {\n return new Promise((resolve, reject) => {\n task.callbacks.add({ resolve, reject });\n });\n }\n\n private resolveRenderTaskCallbacks(task: RenderTask): void {\n for (const callbacks of task.callbacks) {\n callbacks.resolve();\n }\n task.callbacks.clear();\n }\n\n private rejectRenderTaskCallbacks(task: RenderTask, error: Error): void {\n for (const callbacks of task.callbacks) {\n callbacks.reject(error);\n }\n task.callbacks.clear();\n }\n\n private invalidateRenderTasks(): void {\n for (let index = this.queuedTasks.length - 1; index >= 0; index--) {\n const task = this.queuedTasks[index];\n if (task.renderOptionsVersion !== this.renderOptionsVersion) {\n this.removeQueuedTask(task);\n }\n }\n\n for (const task of Array.from(this.activeTaskById.values())) {\n if (\n isRenderTask(task) &&\n task.renderOptionsVersion !== this.renderOptionsVersion\n ) {\n this.removeActiveTask(task);\n }\n }\n }\n\n private clearQueuedInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n if (this.queuedTaskByInstance.get(instance) === task) {\n this.queuedTaskByInstance.delete(instance);\n }\n }\n }\n\n private clearHighlightKey(task: RenderTask): void {\n if (\n task.highlightKey != null &&\n this.taskByHighlightKey.get(task.highlightKey) === task\n ) {\n this.taskByHighlightKey.delete(task.highlightKey);\n }\n }\n\n private trackInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n this.activeRequestByInstance.set(instance, task.id);\n }\n }\n\n private clearInstanceRequests(task: RenderTask): void {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n this.activeRequestByInstance.delete(instance);\n }\n }\n }\n\n private notifyFileInstances(\n task: RenderFileTask,\n result: ThemedFileResult,\n options: RenderFileOptions\n ): void {\n for (const instance of task.instances) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightSuccess(task.request.file, result, options);\n }\n }\n }\n\n private notifyDiffInstances(\n task: RenderDiffTask,\n result: ThemedDiffResult,\n options: RenderDiffOptions\n ): void {\n for (const instance of task.instances) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightSuccess(task.request.diff, result, options);\n }\n }\n }\n\n private notifyHighlightError(task: RenderTask, error: unknown): void {\n for (const instance of getInstances(task)) {\n if (this.activeRequestByInstance.get(instance) === task.id) {\n instance.onHighlightError(error);\n }\n }\n }\n\n private hasMatchingFileInstanceTask(\n instance: FileRendererInstance,\n file: FileContents\n ): boolean {\n for (const task of this.iterateRenderTasks()) {\n if (\n task.type === 'file' &&\n this.isCurrentRenderTask(task) &&\n task.instances.has(instance) &&\n areFilesEqual(file, task.request.file)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private hasMatchingDiffInstanceTask(\n instance: DiffRendererInstance,\n diff: FileDiffMetadata\n ): boolean {\n for (const task of this.iterateRenderTasks()) {\n if (\n task.type === 'diff' &&\n this.isCurrentRenderTask(task) &&\n task.instances.has(instance) &&\n areDiffTargetsEqual(task.request.diff, diff)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private getTaskByHighlightKey(highlightKey: string): RenderTask | undefined {\n const task = this.taskByHighlightKey.get(highlightKey);\n return task != null && this.isCurrentRenderTask(task) ? task : undefined;\n }\n\n private isCurrentRenderTask(task: RenderTask): boolean {\n return task.renderOptionsVersion === this.renderOptionsVersion;\n }\n\n private *iterateRenderTasks(): Generator<RenderTask> {\n for (const task of this.queuedTasks) {\n yield task;\n }\n for (const task of this.activeTaskById.values()) {\n if (isRenderTask(task)) {\n yield task;\n }\n }\n }\n\n private generateRequestId(): WorkerRequestId {\n return `req_${++this.nextRequestId}`;\n }\n}\n\nfunction shouldSyncCustomExtensions(\n request: AllWorkerTasks['request']\n): request is InitializeWorkerRequest | RenderFileRequest | RenderDiffRequest {\n return (\n request.type === 'initialize' ||\n request.type === 'file' ||\n request.type === 'diff'\n );\n}\n\nfunction getLangsFromTask(task: AllWorkerTasks): SupportedLanguages[] {\n const langs = new Set<SupportedLanguages>();\n if (task.type === 'initialize' || task.type === 'set-render-options') {\n return [];\n }\n switch (task.type) {\n case 'file': {\n langs.add(\n task.request.file.lang ??\n getFiletypeFromFileName(task.request.file.name)\n );\n break;\n }\n case 'diff': {\n langs.add(\n task.request.diff.lang ??\n getFiletypeFromFileName(task.request.diff.name)\n );\n langs.add(\n task.request.diff.lang ??\n getFiletypeFromFileName(task.request.diff.prevName ?? '-')\n );\n break;\n }\n }\n langs.delete('text');\n return Array.from(langs);\n}\n\nfunction isRenderTask(task: AllWorkerTasks | undefined): task is RenderTask {\n return task?.type === 'file' || task?.type === 'diff';\n}\n\nfunction getInstances(\n task: RenderTask\n): Set<FileRendererInstance | DiffRendererInstance> {\n return task.instances as Set<FileRendererInstance | DiffRendererInstance>;\n}\n\nfunction normalizeWorkerError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n"],"mappings":"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"}
|
|
@@ -12536,7 +12536,14 @@ function getLineNodes(nodes) {
|
|
|
12536
12536
|
throw new Error("getLineNodes: Unable to find children");
|
|
12537
12537
|
}
|
|
12538
12538
|
//#endregion
|
|
12539
|
-
//#region src/utils/
|
|
12539
|
+
//#region src/utils/getHunkSideBoundaries.ts
|
|
12540
|
+
/** Converts a unified hunk side's start/count into its consumed-file range. */
|
|
12541
|
+
function getHunkSideStartBoundary(start, count) {
|
|
12542
|
+
return start - (count === 0 ? 0 : 1);
|
|
12543
|
+
}
|
|
12544
|
+
function getHunkSideEndBoundary(start, count) {
|
|
12545
|
+
return getHunkSideStartBoundary(start, count) + count;
|
|
12546
|
+
}
|
|
12540
12547
|
function getExpandedRegion({ isPartial, rangeSize, expandedHunks, hunkIndex, collapsedContextThreshold }) {
|
|
12541
12548
|
const normalizedRangeSize = Math.max(rangeSize, 0);
|
|
12542
12549
|
if (normalizedRangeSize === 0 || isPartial) return {
|
|
@@ -12569,8 +12576,8 @@ function getExpandedRegion({ isPartial, rangeSize, expandedHunks, hunkIndex, col
|
|
|
12569
12576
|
function getTrailingContextRangeSize({ fileDiff, errorPrefix }) {
|
|
12570
12577
|
const lastHunk = fileDiff.hunks[fileDiff.hunks.length - 1];
|
|
12571
12578
|
if (lastHunk == null || fileDiff.isPartial || fileDiff.additionLines.length === 0 || fileDiff.deletionLines.length === 0) return 0;
|
|
12572
|
-
const additionRemaining = fileDiff.additionLines.length - (lastHunk.
|
|
12573
|
-
const deletionRemaining = fileDiff.deletionLines.length - (lastHunk.
|
|
12579
|
+
const additionRemaining = fileDiff.additionLines.length - getHunkSideEndBoundary(lastHunk.additionStart, lastHunk.additionCount);
|
|
12580
|
+
const deletionRemaining = fileDiff.deletionLines.length - getHunkSideEndBoundary(lastHunk.deletionStart, lastHunk.deletionCount);
|
|
12574
12581
|
if (additionRemaining <= 0 && deletionRemaining <= 0) return 0;
|
|
12575
12582
|
if (additionRemaining !== deletionRemaining) throw new Error(`${errorPrefix}: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${fileDiff.name}`);
|
|
12576
12583
|
return Math.min(additionRemaining, deletionRemaining);
|
|
@@ -12661,6 +12668,10 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
|
|
|
12661
12668
|
const hunk = diff.hunks[hunkIndex];
|
|
12662
12669
|
if (hunk == null) throw new Error("iterateOverDiff: invalid hunk index");
|
|
12663
12670
|
if (state.shouldBreak()) break;
|
|
12671
|
+
const deletionBoundary = getHunkSideStartBoundary(hunk.deletionStart, hunk.deletionCount);
|
|
12672
|
+
const additionBoundary = getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount);
|
|
12673
|
+
const deletionStartIndex = !diff.isPartial && hunk.deletionCount === 0 ? deletionBoundary : hunk.deletionLineIndex;
|
|
12674
|
+
const additionStartIndex = !diff.isPartial && hunk.additionCount === 0 ? additionBoundary : hunk.additionLineIndex;
|
|
12664
12675
|
const leadingRegion = getExpandedRegion({
|
|
12665
12676
|
isPartial: diff.isPartial,
|
|
12666
12677
|
rangeSize: hunk.collapsedBefore,
|
|
@@ -12690,10 +12701,10 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
|
|
|
12690
12701
|
if (!state.shouldSkip(expandedLineCount, expandedLineCount)) {
|
|
12691
12702
|
let unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.rangeSize;
|
|
12692
12703
|
let splitLineIndex = hunk.splitLineStart - leadingRegion.rangeSize;
|
|
12693
|
-
let deletionLineIndex =
|
|
12694
|
-
let additionLineIndex =
|
|
12695
|
-
let deletionLineNumber =
|
|
12696
|
-
let additionLineNumber =
|
|
12704
|
+
let deletionLineIndex = deletionStartIndex - leadingRegion.rangeSize;
|
|
12705
|
+
let additionLineIndex = additionStartIndex - leadingRegion.rangeSize;
|
|
12706
|
+
let deletionLineNumber = deletionBoundary + 1 - leadingRegion.rangeSize;
|
|
12707
|
+
let additionLineNumber = additionBoundary + 1 - leadingRegion.rangeSize;
|
|
12697
12708
|
if (walkContextLines(state, leadingRegion.fromStart, diffStyle, (index) => {
|
|
12698
12709
|
return state.emit({
|
|
12699
12710
|
hunkIndex,
|
|
@@ -12719,10 +12730,10 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
|
|
|
12719
12730
|
})) break hunkIterator;
|
|
12720
12731
|
unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.fromEnd;
|
|
12721
12732
|
splitLineIndex = hunk.splitLineStart - leadingRegion.fromEnd;
|
|
12722
|
-
deletionLineIndex =
|
|
12723
|
-
additionLineIndex =
|
|
12724
|
-
deletionLineNumber =
|
|
12725
|
-
additionLineNumber =
|
|
12733
|
+
deletionLineIndex = deletionStartIndex - leadingRegion.fromEnd;
|
|
12734
|
+
additionLineIndex = additionStartIndex - leadingRegion.fromEnd;
|
|
12735
|
+
deletionLineNumber = deletionBoundary + 1 - leadingRegion.fromEnd;
|
|
12736
|
+
additionLineNumber = additionBoundary + 1 - leadingRegion.fromEnd;
|
|
12726
12737
|
if (walkContextLines(state, leadingRegion.fromEnd, diffStyle, (index) => {
|
|
12727
12738
|
return state.emit({
|
|
12728
12739
|
hunkIndex,
|
|
@@ -12754,10 +12765,10 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
|
|
|
12754
12765
|
}
|
|
12755
12766
|
let unifiedLineIndex = hunk.unifiedLineStart;
|
|
12756
12767
|
let splitLineIndex = hunk.splitLineStart;
|
|
12757
|
-
let deletionLineIndex =
|
|
12758
|
-
let additionLineIndex =
|
|
12759
|
-
let deletionLineNumber =
|
|
12760
|
-
let additionLineNumber =
|
|
12768
|
+
let deletionLineIndex = deletionStartIndex;
|
|
12769
|
+
let additionLineIndex = additionStartIndex;
|
|
12770
|
+
let deletionLineNumber = deletionBoundary + 1;
|
|
12771
|
+
let additionLineNumber = additionBoundary + 1;
|
|
12761
12772
|
const lastContent = hunk.hunkContent.at(-1);
|
|
12762
12773
|
for (const content of hunk.hunkContent) {
|
|
12763
12774
|
if (state.shouldBreak()) break hunkIterator;
|
|
@@ -13366,16 +13377,45 @@ function renderTwoFiles({ deletionFile, additionFile, deletionInfo, additionInfo
|
|
|
13366
13377
|
//#region src/utils/computeFileOffsets.ts
|
|
13367
13378
|
const LINE_FEED = 10;
|
|
13368
13379
|
const CARRIAGE_RETURN = 13;
|
|
13380
|
+
const DENSE_LINE_BREAK_BLOCK_SIZE = 4;
|
|
13381
|
+
const DENSE_LINE_BREAK_BLOCK_SPAN = 40;
|
|
13369
13382
|
/**
|
|
13370
13383
|
* Computes line start offsets for a string.
|
|
13371
13384
|
*/
|
|
13372
13385
|
function computeLineOffsets(contents) {
|
|
13373
13386
|
const offsets = [0];
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13387
|
+
let carriageReturn = contents.indexOf("\r");
|
|
13388
|
+
let lineFeed = contents.indexOf("\n");
|
|
13389
|
+
let blockStart = 0;
|
|
13390
|
+
let blockBreaks = 0;
|
|
13391
|
+
while (carriageReturn !== -1 || lineFeed !== -1) {
|
|
13392
|
+
let nextOffset;
|
|
13393
|
+
if (carriageReturn !== -1 && (lineFeed === -1 || carriageReturn < lineFeed)) if (lineFeed === carriageReturn + 1) {
|
|
13394
|
+
nextOffset = lineFeed + 1;
|
|
13395
|
+
carriageReturn = contents.indexOf("\r", nextOffset);
|
|
13396
|
+
lineFeed = contents.indexOf("\n", nextOffset);
|
|
13397
|
+
} else {
|
|
13398
|
+
nextOffset = carriageReturn + 1;
|
|
13399
|
+
carriageReturn = contents.indexOf("\r", nextOffset);
|
|
13400
|
+
}
|
|
13401
|
+
else {
|
|
13402
|
+
nextOffset = lineFeed + 1;
|
|
13403
|
+
lineFeed = contents.indexOf("\n", nextOffset);
|
|
13404
|
+
}
|
|
13405
|
+
offsets.push(nextOffset);
|
|
13406
|
+
if (++blockBreaks === DENSE_LINE_BREAK_BLOCK_SIZE) {
|
|
13407
|
+
if (nextOffset - blockStart <= DENSE_LINE_BREAK_BLOCK_SPAN) {
|
|
13408
|
+
for (let i = nextOffset; i < contents.length; i++) {
|
|
13409
|
+
const char = contents.charCodeAt(i);
|
|
13410
|
+
if (char === LINE_FEED || char === CARRIAGE_RETURN) {
|
|
13411
|
+
if (char === CARRIAGE_RETURN && i + 1 < contents.length && contents.charCodeAt(i + 1) === LINE_FEED) i++;
|
|
13412
|
+
offsets.push(i + 1);
|
|
13413
|
+
}
|
|
13414
|
+
}
|
|
13415
|
+
return offsets;
|
|
13416
|
+
}
|
|
13417
|
+
blockStart = nextOffset;
|
|
13418
|
+
blockBreaks = 0;
|
|
13379
13419
|
}
|
|
13380
13420
|
}
|
|
13381
13421
|
return offsets;
|