@@ -25,7 +25,7 @@ type LspSession = {
2525 process : ChildProcess ;
2626 requestId : number ;
2727 pendingRequests : Map < number , PendingLspRequest > ;
28- buffer : string ;
28+ buffer : Buffer ;
2929 initialized : boolean ;
3030 capabilities : LspServerCapabilities ;
3131 disposed : boolean ;
@@ -93,7 +93,7 @@ function createLspSession(serverName: string, child: ChildProcess): LspSession {
9393 process : child ,
9494 requestId : 0 ,
9595 pendingRequests : new Map ( ) ,
96- buffer : "" ,
96+ buffer : Buffer . alloc ( 0 ) ,
9797 initialized : false ,
9898 capabilities : { } ,
9999 disposed : false ,
@@ -105,8 +105,9 @@ function registerActiveLspSession(session: LspSession): void {
105105}
106106
107107function attachLspProcessHandlers ( session : LspSession ) : void {
108- session . process . stdout ?. setEncoding ( "utf-8" ) ;
109- session . process . stdout ?. on ( "data" , ( chunk : string ) => handleIncomingData ( session , chunk ) ) ;
108+ session . process . stdout ?. on ( "data" , ( chunk : Buffer | string ) =>
109+ handleIncomingData ( session , chunk ) ,
110+ ) ;
110111 session . process . stderr ?. setEncoding ( "utf-8" ) ;
111112 session . process . stderr ?. on ( "data" , ( chunk : string ) => {
112113 for ( const line of chunk . split ( / \r ? \n / ) . filter ( Boolean ) ) {
@@ -120,38 +121,39 @@ function encodeLspMessage(body: unknown): string {
120121 return `Content-Length: ${ Buffer . byteLength ( json , "utf-8" ) } \r\n\r\n${ json } ` ;
121122}
122123
123- function parseLspMessages ( buffer : string ) : { messages : unknown [ ] ; remaining : string } {
124+ function parseLspMessages ( buffer : Buffer ) : { messages : unknown [ ] ; remaining : Buffer } {
124125 const messages : unknown [ ] = [ ] ;
125126 let remaining = buffer ;
127+ const headerSeparator = Buffer . from ( "\r\n\r\n" , "ascii" ) ;
126128
127129 while ( true ) {
128- const headerEnd = remaining . indexOf ( "\r\n\r\n" ) ;
130+ const headerEnd = remaining . indexOf ( headerSeparator ) ;
129131 if ( headerEnd === - 1 ) {
130132 break ;
131133 }
132134
133- const header = remaining . slice ( 0 , headerEnd ) ;
135+ const header = remaining . subarray ( 0 , headerEnd ) . toString ( "ascii" ) ;
134136 const match = header . match ( / C o n t e n t - L e n g t h : \s * ( \d + ) / i) ;
135137 if ( ! match ) {
136- remaining = remaining . slice ( headerEnd + 4 ) ;
138+ remaining = remaining . subarray ( headerEnd + headerSeparator . length ) ;
137139 continue ;
138140 }
139141
140142 const contentLength = Number . parseInt ( match [ 1 ] , 10 ) ;
141- const bodyStart = headerEnd + 4 ;
143+ const bodyStart = headerEnd + headerSeparator . length ;
142144 const bodyEnd = bodyStart + contentLength ;
143145
144- if ( Buffer . byteLength ( remaining . slice ( bodyStart ) , "utf-8" ) < contentLength ) {
146+ if ( remaining . length < bodyEnd ) {
145147 break ;
146148 }
147149
148150 try {
149- const body = remaining . slice ( bodyStart , bodyStart + contentLength ) ;
151+ const body = remaining . subarray ( bodyStart , bodyEnd ) . toString ( "utf8" ) ;
150152 messages . push ( JSON . parse ( body ) ) ;
151153 } catch {
152154 // skip malformed
153155 }
154- remaining = remaining . slice ( bodyEnd ) ;
156+ remaining = remaining . subarray ( bodyEnd ) ;
155157 }
156158
157159 return { messages, remaining } ;
@@ -174,10 +176,13 @@ function sendRequest(session: LspSession, method: string, params?: unknown): Pro
174176 } ) ;
175177}
176178
177- function handleIncomingData ( session : LspSession , chunk : string ) {
178- session . buffer += chunk ;
179+ function handleIncomingData ( session : LspSession , chunk : Buffer | string ) {
180+ session . buffer = Buffer . concat ( [
181+ session . buffer ,
182+ typeof chunk === "string" ? Buffer . from ( chunk , "utf8" ) : chunk ,
183+ ] ) ;
179184 const { messages, remaining } = parseLspMessages ( session . buffer ) ;
180- session . buffer = remaining ;
185+ session . buffer = remaining . length === 0 ? Buffer . alloc ( 0 ) : Buffer . from ( remaining ) ;
181186
182187 for ( const msg of messages ) {
183188 if ( typeof msg !== "object" || msg === null ) {
0 commit comments