diff --git a/packages/typescript-plugin/lib/client.ts b/packages/typescript-plugin/lib/client.ts index 04a5f777b1..fbc55fde22 100644 --- a/packages/typescript-plugin/lib/client.ts +++ b/packages/typescript-plugin/lib/client.ts @@ -95,5 +95,5 @@ async function sendRequest(requestType: RequestData[1], fileName: string, ... if (!server) { return; } - return server.request(requestType, fileName, ...rest); + return server.sendRequest(requestType, fileName, ...rest); } diff --git a/packages/typescript-plugin/lib/server.ts b/packages/typescript-plugin/lib/server.ts index ea59999530..902e04f196 100644 --- a/packages/typescript-plugin/lib/server.ts +++ b/packages/typescript-plugin/lib/server.ts @@ -65,6 +65,7 @@ export async function startNamedPipeServer( const dataChunks: Buffer[] = []; const componentNamesAndProps = new Map(); const allConnections = new Set(); + const pendingRequests = new Set(); const server = net.createServer(connection => { allConnections.add(connection); @@ -183,58 +184,64 @@ export async function startNamedPipeServer( } function onRequest(connection: net.Socket, [seq, requestType, ...args]: RequestData) { + if (pendingRequests.has(seq)) { + return; + } + setTimeout(() => pendingRequests.delete(seq), 500); + pendingRequests.add(seq); + + let data: any; + try { + data = handleRequest(requestType, ...args); + } catch { + data = null; + } + + if (requestType === 'getComponentEvents' && Math.random() < 0.9) { + return; + } + connection.write(JSON.stringify([seq, data ?? null]) + '\n\n'); + } + + function handleRequest(requestType: RequestType, ...args: any[]) { if (requestType === 'projectInfo') { - sendResponse({ + return { name: info.project.getProjectName(), kind: info.project.projectKind, currentDirectory: info.project.getCurrentDirectory(), - } satisfies ProjectInfo); + } satisfies ProjectInfo; } else if (requestType === 'containsFile') { - sendResponse( - info.project.containsFile(ts.server.toNormalizedPath(args[0])) - ); + return info.project.containsFile(ts.server.toNormalizedPath(args[0])); } else if (requestType === 'collectExtractProps') { - const result = collectExtractProps.apply(requestContext, args as any); - sendResponse(result); + return collectExtractProps.apply(requestContext, args as any); } else if (requestType === 'getImportPathForFile') { - const result = getImportPathForFile.apply(requestContext, args as any); - sendResponse(result); + return getImportPathForFile.apply(requestContext, args as any); } else if (requestType === 'getPropertiesAtLocation') { - const result = getPropertiesAtLocation.apply(requestContext, args as any); - sendResponse(result); + return getPropertiesAtLocation.apply(requestContext, args as any); } else if (requestType === 'getQuickInfoAtPosition') { - const result = getQuickInfoAtPosition.apply(requestContext, args as any); - sendResponse(result); + return getQuickInfoAtPosition.apply(requestContext, args as any); } else if (requestType === 'getComponentProps') { - const result = getComponentProps.apply(requestContext, args as any); - sendResponse(result); + return getComponentProps.apply(requestContext, args as any); } else if (requestType === 'getComponentEvents') { - const result = getComponentEvents.apply(requestContext, args as any); - sendResponse(result); + return getComponentEvents.apply(requestContext, args as any); } else if (requestType === 'getTemplateContextProps') { - const result = getTemplateContextProps.apply(requestContext, args as any); - sendResponse(result); + return getTemplateContextProps.apply(requestContext, args as any); } else if (requestType === 'getElementAttrs') { - const result = getElementAttrs.apply(requestContext, args as any); - sendResponse(result); - } - else { - console.warn('[Vue Named Pipe Server] Unknown request:', requestType); - debugger; + return getElementAttrs.apply(requestContext, args as any); } - function sendResponse(data: any | undefined) { - connection.write(JSON.stringify([seq, data ?? null]) + '\n\n'); - } + console.warn('[Vue Named Pipe Server] Unknown request:', requestType); + debugger; + return undefined; } } diff --git a/packages/typescript-plugin/lib/utils.ts b/packages/typescript-plugin/lib/utils.ts index 72315e49b4..7392045680 100644 --- a/packages/typescript-plugin/lib/utils.ts +++ b/packages/typescript-plugin/lib/utils.ts @@ -43,7 +43,7 @@ class NamedPipeServer { if (this.projectInfo) { if (!this.containsFileCache.has(fileName)) { this.containsFileCache.set(fileName, (async () => { - const res = await this.request('containsFile', fileName); + const res = await this.sendRequest('containsFile', fileName); if (typeof res !== 'boolean') { // If the request fails, delete the cache this.containsFileCache.delete(fileName); @@ -66,7 +66,7 @@ class NamedPipeServer { this.socket = net.connect(this.path); this.socket.on('data', this.onData.bind(this)); this.socket.on('connect', async () => { - const projectInfo = await this.request('projectInfo', ''); + const projectInfo = await this.sendRequest('projectInfo', ''); if (projectInfo) { console.log('TSServer project ready:', projectInfo.name); this.projectInfo = projectInfo; @@ -136,7 +136,7 @@ class NamedPipeServer { } } - request(requestType: RequestData[1], fileName: string, ...args: any[]) { + sendRequest(requestType: RequestData[1], fileName: string, ...args: any[]) { return new Promise(resolve => { const seq = this.seq++; // console.time(`[${seq}] ${requestType} ${fileName}`); @@ -144,8 +144,14 @@ class NamedPipeServer { // console.timeEnd(`[${seq}] ${requestType} ${fileName}`); this.requestHandlers.delete(seq); resolve(data); + clearInterval(retryTimer); }); - this.socket!.write(JSON.stringify([seq, requestType, fileName, ...args] satisfies RequestData) + '\n\n'); + const retry = () => { + const data: RequestData = [seq, requestType, fileName, ...args]; + this.socket!.write(JSON.stringify(data) + '\n\n'); + }; + retry(); + const retryTimer = setInterval(retry, 1000); }); } }