Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

2 changes: 0 additions & 2 deletions packages/diff-view/src/parts/Initialize/Initialize.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { TextMeasurementWorker } from '@lvce-editor/rpc-registry'
import type { DiffViewState } from '../DiffViewState/DiffViewState.ts'
import { createExtensionHostRpc } from '../CreateExtensionHostRpc/CreateExtensionHostRpc.ts'
import { createTextMeasurementWorkerRpc } from '../CreateTextMeasurementWorkerRpc/CreateTextMeasurementWorkerRpc.ts'
import { getKeys, get as getDiffViewState, set as setDiffViewState } from '../DiffViewStates/DiffViewStates.ts'
import { initializeDiffWorker } from '../InitializeDiffWorker/InitializeDiffWorker.ts'
Expand Down Expand Up @@ -30,7 +29,6 @@ const measureCharWidth = async (state: DiffViewState): Promise<number | undefine

export const initialize = async (): Promise<void> => {
await Promise.all([
createExtensionHostRpc(),
createTextMeasurementWorkerRpc(),
initializeDiffWorker(),
initializeExtensionManagementWorker(),
Expand Down
24 changes: 19 additions & 5 deletions packages/diff-view/src/parts/ReadFile/ReadFile.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import { ExtensionHost, FileSystemWorker, RendererWorker } from '@lvce-editor/rpc-registry'
import { getPath } from '../GetPath/GetPath.ts'
import { ExtensionManagementWorker, FileSystemWorker, RendererWorker } from '@lvce-editor/rpc-registry'
import { getProtocol } from '../GetProtocol/GetProtocol.ts'
import { toFileUri } from '../ToFileUri/ToFileUri.ts'

interface FileSystemProviderResult {
readonly found: boolean
readonly result?: unknown
}

const readExtensionFile = async (protocol: string, uri: string): Promise<string> => {
const response = (await ExtensionManagementWorker.invoke('Extensions.executeFileSystemProviderReadFile', protocol, uri)) as FileSystemProviderResult
if (!response.found) {
throw new Error(`no file system provider found for ${protocol}`)
}
if (typeof response.result !== 'string') {
throw new TypeError(`expected file system provider ${protocol} to return a string`)
}
return response.result
}

export const readFile = async (uri: string): Promise<string> => {
if (!uri || uri.startsWith('untitled://')) {
return ''
Expand All @@ -17,9 +32,8 @@ export const readFile = async (uri: string): Promise<string> => {
if (protocol === 'fetch') {
return RendererWorker.readFile(uri)
}
const path = getPath(protocol, uri)
if (protocol === 'memfs') {
return ExtensionHost.invoke('FileSystemMemory.readFile', path)
return RendererWorker.readFile(uri)
}
return ExtensionHost.invoke('ExtensionHostFileSystem.readFile', protocol, path)
return readExtensionFile(protocol, uri)
}

This file was deleted.

9 changes: 3 additions & 6 deletions packages/diff-view/test/Initialize.test.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import { expect, test } from '@jest/globals'
import { ExtensionHost, RendererWorker, TextMeasurementWorker } from '@lvce-editor/rpc-registry'
import { RendererWorker, TextMeasurementWorker } from '@lvce-editor/rpc-registry'
import { initialize } from '../src/parts/Initialize/Initialize.ts'

test('initialize should set ExtensionHost and TextMeasurementWorker RPCs', async (): Promise<void> => {
test('initialize should set TextMeasurementWorker RPC', async (): Promise<void> => {
const commandMap = {
'RendererWorker.sendMessagePortToDiffWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToErrorWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToExtensionHostWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToExtensionManagementWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToFileSystemWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToSyntaxHighlightingWorker': async (): Promise<void> => {},
'RendererWorker.sendMessagePortToTextMeasurementWorker': async (): Promise<void> => {},
'SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker': async (): Promise<void> => {},
'SendMessagePortToExtensionHostWorker.sendMessagePortToTextMeasurementWorker': async (): Promise<void> => {},
'SendMessagePortToTextMeasurementWorker.sendMessagePortToTextMeasurementWorker': async (): Promise<void> => {},
}
RendererWorker.registerMockRpc(commandMap)

await initialize()

expect(typeof ExtensionHost.invoke).toBe('function')
expect(typeof TextMeasurementWorker.invoke).toBe('function')
await Promise.all([ExtensionHost.dispose(), TextMeasurementWorker.dispose()])
await TextMeasurementWorker.dispose()
})
20 changes: 1 addition & 19 deletions packages/diff-view/test/LoadContent.test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import { expect, jest, test } from '@jest/globals'
import { RpcId } from '@lvce-editor/constants'
import { DiffWorker, ExtensionHost, ExtensionManagementWorker, FileSystemWorker, SyntaxHighlightingWorker } from '@lvce-editor/rpc-registry'
import { DiffWorker, ExtensionManagementWorker, FileSystemWorker, SyntaxHighlightingWorker } from '@lvce-editor/rpc-registry'
import { registerMockRpc } from '@lvce-editor/rpc-registry'
import { createDefaultState } from '../src/parts/CreateDefaultState/CreateDefaultState.ts'
import { loadContent } from '../src/parts/LoadContent/LoadContent.ts'
import { VisibleLineType } from '../src/parts/VisibleLine/VisibleLine.ts'

test('loadContent loads both sides of an inline diff uri', async (): Promise<void> => {
const extensionHostRpc = ExtensionHost.registerMockRpc({
'ExtensionHostFileSystem.readFile': async (protocol: string, path: string): Promise<string> => {
if (protocol === 'data' && path === 'before-content') {
return 'before-content'
}
if (protocol === 'file' && path === '/tmp/after.txt') {
return 'after-content\nsecond-line'
}
throw new Error(`unexpected params: ${protocol} ${path}`)
},
})
const fileSystemWorkerRpc = FileSystemWorker.registerMockRpc({
'FileSystem.readFile': async (uri: string): Promise<string> => {
if (uri === 'file:///tmp/after.txt') {
Expand Down Expand Up @@ -48,7 +37,6 @@ test('loadContent loads both sides of an inline diff uri', async (): Promise<voi
const result = await loadContent(state, { minLineY: 1 })

expect(diffWorkerRpc.invocations).toEqual([['Diff.diffInline', ['before-content'], ['after-content', 'second-line']]])
expect(extensionHostRpc.invocations).toEqual([])
expect(fileSystemWorkerRpc.invocations).toEqual([['FileSystem.readFile', 'file:///tmp/after.txt']])
expect(result).toMatchObject({
contentLeft: 'before-content',
Expand Down Expand Up @@ -129,11 +117,6 @@ test('loadContent stores pane load errors instead of throwing', async (): Promis
}
},
})
const extensionHostRpc = ExtensionHost.registerMockRpc({
'ExtensionHostFileSystem.readFile': async (): Promise<string> => {
throw new Error('should not invoke extension host')
},
})
const fileSystemWorkerRpc = FileSystemWorker.registerMockRpc({
'FileSystem.readFile': async (uri: string): Promise<string> => {
if (uri === 'file:///tmp/missing.txt') {
Expand All @@ -158,7 +141,6 @@ test('loadContent stores pane load errors instead of throwing', async (): Promis

const result = await loadContent(state, { minLineY: 0 })

expect(extensionHostRpc.invocations).toEqual([])
expect(errorWorkerRpc.invocations).toEqual([['Errors.prepare', error]])
expect(fileSystemWorkerRpc.invocations).toEqual([['FileSystem.readFile', 'file:///tmp/missing.txt']])
expect(diffWorkerRpc.invocations).toEqual([])
Expand Down
31 changes: 1 addition & 30 deletions packages/diff-view/test/LoadFileContents.test.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
import { expect, test } from '@jest/globals'
import { ExtensionHost, FileSystemWorker } from '@lvce-editor/rpc-registry'
import { FileSystemWorker } from '@lvce-editor/rpc-registry'
import { loadFileContents } from '../src/parts/LoadFileContents/LoadFileContents.ts'

test('loadFileContents loads both files in order', async (): Promise<void> => {
const extensionHostInvocations: unknown[][] = []
const fileSystemWorkerInvocations: unknown[][] = []
const extensionHostRpc = {
dispose: (): void => {},
invoke: async (method: string, ...params: readonly unknown[]): Promise<string> => {
extensionHostInvocations.push([method, ...params])
if (method !== 'ExtensionHostFileSystem.readFile') {
throw new Error(`unexpected method: ${method}`)
}
const [protocol, path] = params
if (protocol === 'data' && path === 'before-content') {
return 'before-content'
}
if (protocol === 'file' && path === '/tmp/after.txt') {
return 'after-content'
}
throw new Error(`unexpected params: ${String(protocol)} ${String(path)}`)
},
set: (): void => {},
}
const fileSystemWorkerRpc = {
dispose: (): void => {},
invoke: async (method: string, ...params: readonly unknown[]): Promise<string> => {
Expand All @@ -38,12 +19,10 @@ test('loadFileContents loads both files in order', async (): Promise<void> => {
},
set: (): void => {},
}
ExtensionHost.set(extensionHostRpc as any)
FileSystemWorker.set(fileSystemWorkerRpc as any)

const result = await loadFileContents('data://before-content', '/tmp/after.txt')

expect(extensionHostInvocations).toEqual([])
expect(fileSystemWorkerInvocations).toEqual([['FileSystem.readFile', 'file:///tmp/after.txt']])
expect(result).toEqual({
contentLeft: 'before-content',
Expand All @@ -62,13 +41,6 @@ test('loadFileContents captures per-side read errors', async (): Promise<void> =
Object.defineProperty(error, 'stack', {
value: 'Error: file not found\n at read missing file',
})
const extensionHostRpc = {
dispose: (): void => {},
invoke: async (): Promise<string> => {
throw new Error('should not invoke extension host')
},
set: (): void => {},
}
const fileSystemWorkerRpc = {
dispose: (): void => {},
invoke: async (method: string, ...params: readonly unknown[]): Promise<string> => {
Expand All @@ -83,7 +55,6 @@ test('loadFileContents captures per-side read errors', async (): Promise<void> =
},
set: (): void => {},
}
ExtensionHost.set(extensionHostRpc as any)
FileSystemWorker.set(fileSystemWorkerRpc as any)

const result = await loadFileContents('data://before-content', '/tmp/after.txt')
Expand Down
76 changes: 25 additions & 51 deletions packages/diff-view/test/ReadFile.test.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,20 @@
import { expect, test } from '@jest/globals'
import { ExtensionHost, FileSystemWorker, RendererWorker } from '@lvce-editor/rpc-registry'
import { ExtensionManagementWorker, FileSystemWorker, RendererWorker } from '@lvce-editor/rpc-registry'
import { readFile } from '../src/parts/ReadFile/ReadFile.ts'

test('readFile returns empty content for untitled uri', async (): Promise<void> => {
const mockRpc = {
dispose: (): void => {},
invocations: [] as readonly unknown[][],
invoke: async (method: string, ...params: readonly unknown[]): Promise<string> => {
mockRpc.invocations = [...mockRpc.invocations, [method, ...params]]
throw new Error('should not invoke rpc')
},
set: (): void => {},
}
ExtensionHost.set(mockRpc as any)

const result = await readFile('untitled://Untitled-1')

expect(result).toBe('')
expect(mockRpc.invocations).toEqual([])
})

test('readFile returns inline content for data uri', async (): Promise<void> => {
const mockRpc = {
dispose: (): void => {},
invocations: [] as readonly unknown[][],
invoke: async (method: string, ...params: readonly unknown[]): Promise<string> => {
mockRpc.invocations = [...mockRpc.invocations, [method, ...params]]
throw new Error(`unexpected method: ${method} ${params.join(' ')}`)
},
set: (): void => {},
}
ExtensionHost.set(mockRpc as any)

const result = await readFile('data://before-content')

expect(result).toBe('before-content')
expect(mockRpc.invocations).toEqual([])
})

test('readFile reads file content through file system worker', async (): Promise<void> => {
const extensionHostRpc = ExtensionHost.registerMockRpc({
'ExtensionHostFileSystem.readFile': async (): Promise<string> => {
throw new Error('should not call extension host for file uris')
},
})
const fileSystemWorkerRpc = FileSystemWorker.registerMockRpc({
'FileSystem.readFile': async (uri: string): Promise<string> => {
if (uri !== 'file:///tmp/after.txt') {
Expand All @@ -56,15 +27,14 @@ test('readFile reads file content through file system worker', async (): Promise
const result = await readFile('/tmp/after.txt')

expect(result).toBe('after-content')
expect(extensionHostRpc.invocations).toEqual([])
expect(fileSystemWorkerRpc.invocations).toEqual([['FileSystem.readFile', 'file:///tmp/after.txt']])
})

test('readFile reads memfs content through the memory file system command', async (): Promise<void> => {
const extensionHostRpc = ExtensionHost.registerMockRpc({
'FileSystemMemory.readFile': async (path: string): Promise<string> => {
if (path !== '/workspace/file.txt') {
throw new Error(`unexpected params: ${path}`)
test('readFile reads memfs content through the renderer file system', async (): Promise<void> => {
const rendererWorkerRpc = RendererWorker.registerMockRpc({
'FileSystem.readFile': async (uri: string): Promise<string> => {
if (uri !== 'memfs:///workspace/file.txt') {
throw new Error(`unexpected params: ${uri}`)
}
return 'memfs-content'
},
Expand All @@ -73,15 +43,10 @@ test('readFile reads memfs content through the memory file system command', asyn
const result = await readFile('memfs:///workspace/file.txt')

expect(result).toBe('memfs-content')
expect(extensionHostRpc.invocations).toEqual([['FileSystemMemory.readFile', '/workspace/file.txt']])
expect(rendererWorkerRpc.invocations).toEqual([['FileSystem.readFile', 'memfs:///workspace/file.txt']])
})

test('readFile reads fetch content through renderer file system', async (): Promise<void> => {
const extensionHostRpc = ExtensionHost.registerMockRpc({
'ExtensionHostFileSystem.readFile': async (): Promise<string> => {
throw new Error('should not call extension host file system for fetch uris')
},
})
const rendererWorkerRpc = RendererWorker.registerMockRpc({
'FileSystem.readFile': async (uri: string): Promise<string> => {
if (uri !== 'fetch:///playground/package-lock.json') {
Expand All @@ -94,22 +59,31 @@ test('readFile reads fetch content through renderer file system', async (): Prom
const result = await readFile('fetch:///playground/package-lock.json')

expect(result).toBe('fetch-content')
expect(extensionHostRpc.invocations).toEqual([])
expect(rendererWorkerRpc.invocations).toEqual([['FileSystem.readFile', 'fetch:///playground/package-lock.json']])
})

test('readFile reads non-file protocols through extension host', async (): Promise<void> => {
const extensionHostRpc = ExtensionHost.registerMockRpc({
'ExtensionHostFileSystem.readFile': async (protocol: string, path: string): Promise<string> => {
if (protocol !== 'git' || path !== 'HEAD~1:src/file.ts') {
throw new Error(`unexpected params: ${protocol} ${path}`)
test('readFile reads extension protocols through extension management worker', async (): Promise<void> => {
const extensionManagementWorkerRpc = ExtensionManagementWorker.registerMockRpc({
'Extensions.executeFileSystemProviderReadFile': async (protocol: string, uri: string): Promise<unknown> => {
if (protocol !== 'git-file-before' || uri !== 'git-file-before://file:///workspace/src/file.ts') {
throw new Error(`unexpected params: ${protocol} ${uri}`)
}
return 'git-content'
return { found: true, result: 'git-content' }
},
})

const result = await readFile('git://HEAD~1:src/file.ts')
const result = await readFile('git-file-before://file:///workspace/src/file.ts')

expect(result).toBe('git-content')
expect(extensionHostRpc.invocations).toEqual([['ExtensionHostFileSystem.readFile', 'git', 'HEAD~1:src/file.ts']])
expect(extensionManagementWorkerRpc.invocations).toEqual([
['Extensions.executeFileSystemProviderReadFile', 'git-file-before', 'git-file-before://file:///workspace/src/file.ts'],
])
})

test('readFile rejects when no isolated extension provides the protocol', async (): Promise<void> => {
ExtensionManagementWorker.registerMockRpc({
'Extensions.executeFileSystemProviderReadFile': async (): Promise<unknown> => ({ found: false }),
})

await expect(readFile('missing:///workspace/file.txt')).rejects.toThrow('no file system provider found for missing')
})