@@ -186,7 +186,6 @@ const ipcRenderer = {
186186
187187const ipcMessagePort = {
188188 acquire : ( responseChannel : string , nonce : string ) => {
189-
190189 // Create an in-memory MessageChannel.
191190 // port2 is posted to the window so acquirePort() (ipc.mp.ts) picks it up
192191 // via its window 'message' listener (filters e.data === nonce && e.ports[0]).
@@ -200,19 +199,28 @@ const ipcMessagePort = {
200199 port1 . start ( ) ;
201200
202201 let HandshakeComplete = false ;
203-
204- port1 . onmessage = ( Event : MessageEvent ) => {
205- if ( HandshakeComplete ) {
206- // After handshake, silently drop extension-host protocol
207- // messages (activate, executeCommand, etc.) until
208- // a real Cocoon relay is wired.
209- return ;
202+ let MessageCount = 0 ;
203+
204+ const ForwardToMountain = ( Data : ArrayBuffer | Uint8Array ) => {
205+ // Forward binary extension host protocol messages to Mountain
206+ // for relay to Cocoon via gRPC. Mountain will handle decoding.
207+ const Invoke =
208+ ( window as any ) . __TAURI__ ?. core ?. invoke ??
209+ ( window as any ) . __TAURI__ ?. invoke ;
210+
211+ if ( typeof Invoke === "function" ) {
212+ const Bytes =
213+ Data instanceof Uint8Array
214+ ? Array . from ( Data )
215+ : Array . from ( new Uint8Array ( Data ) ) ;
216+ Invoke ( "MountainIPCInvoke" , {
217+ method : "cocoon:extensionHostMessage" ,
218+ params : [ { data : Bytes , responseChannel } ] ,
219+ } ) . catch ( ( ) => { } ) ;
210220 }
221+ } ;
211222
212- // The first large message from VS Code is the init data
213- // (JSON-encoded IExtensionHostInitData wrapped in VSBuffer).
214- // Any message with byteLength > 1 is init data; single-byte
215- // messages are control (Ready=2, Initialized=1, Terminate=3).
223+ port1 . onmessage = ( Event : MessageEvent ) => {
216224 const Data = Event . data ;
217225 const Length =
218226 Data instanceof ArrayBuffer
@@ -223,13 +231,58 @@ const ipcMessagePort = {
223231 ? Data . byteLength
224232 : 0 ;
225233
226- if ( Length > 1 ) {
227- HandshakeComplete = true ;
228- // MessageType.Initialized → byte 1
229- port1 . postMessage ( new Uint8Array ( [ 1 ] ) ) ;
234+ if ( ! HandshakeComplete ) {
235+ // The first large message from VS Code is the init data
236+ // (JSON-encoded IExtensionHostInitData wrapped in VSBuffer).
237+ // Any message with byteLength > 1 is init data; single-byte
238+ // messages are control (Ready=2, Initialized=1, Terminate=3).
239+ if ( Length > 1 ) {
240+ HandshakeComplete = true ;
241+ try {
242+ performance . mark ( "land:exthost:handshake-complete" ) ;
243+ } catch { }
244+
245+ // Forward init data to Mountain for Cocoon
246+ ForwardToMountain (
247+ Data instanceof Uint8Array
248+ ? Data
249+ : new Uint8Array ( Data ) ,
250+ ) ;
251+
252+ // MessageType.Initialized → byte 1
253+ port1 . postMessage ( new Uint8Array ( [ 1 ] ) ) ;
254+ }
255+ return ;
256+ }
257+
258+ // Post-handshake: forward extension host protocol messages
259+ MessageCount ++ ;
260+ try {
261+ performance . mark ( `land:exthost:message:${ MessageCount } ` , {
262+ detail : { bytes : Length } ,
263+ } ) ;
264+ } catch { }
265+
266+ if ( Length > 0 ) {
267+ ForwardToMountain (
268+ Data instanceof Uint8Array ? Data : new Uint8Array ( Data ) ,
269+ ) ;
230270 }
231271 } ;
232272
273+ // Listen for Cocoon → workbench messages via Tauri events
274+ const TauriListen = ( window as any ) . __TAURI__ ?. event ?. listen ;
275+ if ( typeof TauriListen === "function" ) {
276+ TauriListen (
277+ "cocoon:extensionHostReply" ,
278+ ( Event : { payload : { data : number [ ] } } ) => {
279+ if ( Event ?. payload ?. data ) {
280+ port1 . postMessage ( new Uint8Array ( Event . payload . data ) ) ;
281+ }
282+ } ,
283+ ) . catch ( ( ) => { } ) ;
284+ }
285+
233286 // Send Ready after a tick so VS Code's onMessage listener is registered.
234287 // MessageType.Ready → byte 2
235288 setTimeout ( ( ) => {
0 commit comments