Repository: microsoft/vscode-edge-devtools
Pull request #89 (2019-08-02 00:42:40)

Bubbling up close message from websocket to the extension.
This PR bubbles up the close message from the websocket to the extension, so when the websocket is closed the extension will be closed too.


Patch:
diff --git a/src/devtoolsPanel.ts b/src/devtoolsPanel.ts
index 758f09e..2e8a213 100644
--- a/src/devtoolsPanel.ts
+++ b/src/devtoolsPanel.ts
@@ -57,6 +57,7 @@ export class DevToolsPanel {
         this.panelSocket.on("setState", (msg) => this.onSocketSetState(msg));
         this.panelSocket.on("getUrl", (msg) => this.onSocketGetUrl(msg));
         this.panelSocket.on("openInEditor", (msg) => this.onSocketOpenInEditor(msg));
+        this.panelSocket.on("close", () => this.onSocketClose());
 
         // Handle closing
         this.panel.onDidDispose(() => {
@@ -113,6 +114,10 @@ export class DevToolsPanel {
         // TODO: Handle message
     }
 
+    private onSocketClose() {
+        this.dispose();
+    }
+
     private onSocketTelemetry(message: string) {
         const telemetry: TelemetryData = JSON.parse(message);
 
diff --git a/src/panelSocket.ts b/src/panelSocket.ts
index a46eb72..7e4e000 100644
--- a/src/panelSocket.ts
+++ b/src/panelSocket.ts
@@ -106,7 +106,9 @@ export class PanelSocket extends EventEmitter {
         if (this.isConnected) {
             // Tell the devtools that the real websocket was closed
             this.postMessageToDevTools("close");
+            this.emit("close");
         }
+
         this.isConnected = false;
     }
 }


Test patch:
diff --git a/src/devtoolsPanel.test.ts b/src/devtoolsPanel.test.ts
index 466b7b9..f7a46aa 100644
--- a/src/devtoolsPanel.test.ts
+++ b/src/devtoolsPanel.test.ts
@@ -161,10 +161,15 @@ describe("devtoolsPanel", () => {
             const dtp = await import("./devtoolsPanel");
             dtp.DevToolsPanel.createOrShow(context, mockTelemetry, "", mockRuntimeConfig);
 
-            expect(mockPanelSocket.on).toHaveBeenCalledTimes(Object.keys(webviewEventNames).length);
+            // The +1 in here is due to the 'close' event. This is an extension event not raised from the Webview.
+            expect(mockPanelSocket.on).toHaveBeenCalledTimes(Object.keys(webviewEventNames).length + 1);
             for (const e of webviewEventNames) {
                 expect(hookedEvents).toContain(e);
             }
+
+            // Close is raised from the extension side in response to websocket close.
+            // so it does not require a Webview event, we verify manually for this case.
+            expect(hookedEvents).toContain("close");
         });
 
         it("forwards webview messages to the panel socket", async () => {
@@ -307,6 +312,13 @@ describe("devtoolsPanel", () => {
                 expect(mockPanel.webview.postMessage).toHaveBeenCalledWith(expectedPostedMessage);
             });
 
+            it("dispose devtools panel on socket close", async () => {
+                const dtp = await import("./devtoolsPanel");
+                dtp.DevToolsPanel.createOrShow(context, mockTelemetry, "", mockRuntimeConfig);
+                hookedEvents.get("close")!();
+                expect(mockPanelSocket.dispose).toBeCalled();
+            });
+
             it("posts defaults for get state", async () => {
                 (context.workspaceState.get as jest.Mock).mockReturnValue(null);