From 32f609eeb3eb7e9790b9a5158842bc68e458397d Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 27 Jun 2022 15:48:11 +0800 Subject: [PATCH 01/24] =?UTF-8?q?feat:=20=E6=8D=95=E8=8E=B7MessageConnecti?= =?UTF-8?q?on=E7=9A=84=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/connection/src/common/message.ts | 41 ++++++++++++++++++++++- packages/connection/src/common/proxy.ts | 23 ++++++++++++- packages/connection/src/node/connect.ts | 31 +++++++++++++++-- 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/packages/connection/src/common/message.ts b/packages/connection/src/common/message.ts index a68c297b5e..0caecc909e 100644 --- a/packages/connection/src/common/message.ts +++ b/packages/connection/src/common/message.ts @@ -83,11 +83,50 @@ export class WebSocketMessageWriter extends AbstractMessageWriter implements Mes public end(): void {} } +declare global { + interface Window { + __OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__: any; + } +} + /** * 给服务端的 WebSocket 及 Browser 端的 WebSocket 实例共用的方法 * @param socket * @returns */ export function createWebSocketConnection(socket: any) { - return createMessageConnection(new WebSocketMessageReader(socket), new WebSocketMessageWriter(socket)); + // return createMessageConnection(new WebSocketMessageReader(socket), new WebSocketMessageWriter(socket)); + + const messageConnection = createMessageConnection( + new WebSocketMessageReader(socket), + new WebSocketMessageWriter(socket), + ); + + // sendRequest是有回复的,在proxy.ts中处理requestResult + const messageConnectionProxy = new Proxy(messageConnection, { + get(target, prop) { + if (prop === 'sendRequest' || prop === 'sendNotification') { + return function (...args: any) { + // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.send([prop, ...args]); + } + return target[prop].apply(target, [...args]); + }; + } + + // onNotification很多的,onRequest我都试不出来 + if (prop === 'onRequest' || prop === 'onNotification') { + return function (...args: any) { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + } + return target[prop].apply(target, [...args]); + }; + } + return target[prop]; + }, + }); + + return messageConnectionProxy; } diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 136083fa08..de97832547 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -126,8 +126,14 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['错误', error]); + } reject(error); } else { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['requestResult', result.data]); + } resolve(result.data); } }); @@ -163,8 +169,20 @@ export class RPCProxy { methods.forEach((method) => { if (method.startsWith('on')) { connection.onNotification(method, (...args) => this.onNotification(method, ...args)); + connection.onNotification(method, (...args) => { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['onNotification', method, ...args]); + } + this.onNotification(method, ...args); + }); } else { - connection.onRequest(method, (...args) => this.onRequest(method, ...args)); + // connection.onRequest(method, (...args) => this.onRequest(method, ...args)); + connection.onRequest(method, (...args) => { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['onRequest', method, ...args]); + } + return this.onRequest(method, ...args); + }); } if (cb) { @@ -174,6 +192,9 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(`onRequest: ${method} is not registered!`); + } return { data: NOTREGISTERMETHOD, }; diff --git a/packages/connection/src/node/connect.ts b/packages/connection/src/node/connect.ts index 1cc31dafe3..c9d80980cb 100644 --- a/packages/connection/src/node/connect.ts +++ b/packages/connection/src/node/connect.ts @@ -6,7 +6,34 @@ import { createMessageConnection, } from '@opensumi/vscode-jsonrpc/lib/node/main'; - export function createSocketConnection(socket: net.Socket) { - return createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); + // return createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); + + const messageConnection = createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); + + const messageConnectionProxy = new Proxy(messageConnection, { + get(target, prop) { + if (prop === 'sendRequest' || prop === 'sendNotification') { + return function (...args: any) { + // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.send([prop, ...args]); + } + return target[prop].apply(target, [...args]); + }; + } + + if (prop === 'onRequest' || prop === 'onNotification') { + return function (...args: any) { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + } + return target[prop].apply(target, [...args]); + }; + } + return target[prop]; + }, + }); + + return messageConnectionProxy; } From b226ceaaf4471932e7e39436ab06167c234e62ab Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 27 Jun 2022 15:48:54 +0800 Subject: [PATCH 02/24] =?UTF-8?q?feat:=20=E5=8A=A0=E8=BD=BDopensumi-devtoo?= =?UTF-8?q?ls=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/electron/src/main/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/electron/src/main/index.ts b/tools/electron/src/main/index.ts index 537f95710f..cf620013b2 100644 --- a/tools/electron/src/main/index.ts +++ b/tools/electron/src/main/index.ts @@ -1,6 +1,6 @@ import { join } from 'path'; -import { app } from 'electron'; +import { app, session } from 'electron'; import { URI } from '@opensumi/ide-core-common'; import { ElectronMainApp } from '@opensumi/ide-core-electron-main'; @@ -31,4 +31,10 @@ const electronApp = new ElectronMainApp({ electronApp.init().then(() => { electronApp.loadWorkspace(); + + // const devtronPath = join(require('os').homedir(), 'Projects/ASOC2022/devtron'); + // session.defaultSession.loadExtension(devtronPath); + + const opensumicrxPath = join(require('os').homedir(), 'Projects/ASOC2022/opensumi/opensumi-crx/build'); + session.defaultSession.loadExtension(opensumicrxPath); }); From 46dab653ef1f38b9def23d1aeea4982e312be649 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Tue, 28 Jun 2022 12:32:07 +0800 Subject: [PATCH 03/24] =?UTF-8?q?chore:=20onRequest=E5=92=8ConNotification?= =?UTF-8?q?=E7=9A=84=E5=BA=94=E6=8B=A6=E6=88=AA=E5=8F=91=E7=94=9F=E5=9C=A8?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E7=9A=84handler=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不能像sendRequest和sendNotification这么来 --- packages/connection/src/common/message.ts | 16 ++++++++-------- packages/connection/src/node/connect.ts | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/connection/src/common/message.ts b/packages/connection/src/common/message.ts index 0caecc909e..20773139fd 100644 --- a/packages/connection/src/common/message.ts +++ b/packages/connection/src/common/message.ts @@ -116,14 +116,14 @@ export function createWebSocketConnection(socket: any) { } // onNotification很多的,onRequest我都试不出来 - if (prop === 'onRequest' || prop === 'onNotification') { - return function (...args: any) { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); - } - return target[prop].apply(target, [...args]); - }; - } + // if (prop === 'onRequest' || prop === 'onNotification') { + // return function (...args: any) { + // if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + // window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + // } + // return target[prop].apply(target, [...args]); + // }; + // } return target[prop]; }, }); diff --git a/packages/connection/src/node/connect.ts b/packages/connection/src/node/connect.ts index c9d80980cb..e1661813e2 100644 --- a/packages/connection/src/node/connect.ts +++ b/packages/connection/src/node/connect.ts @@ -23,14 +23,14 @@ export function createSocketConnection(socket: net.Socket) { }; } - if (prop === 'onRequest' || prop === 'onNotification') { - return function (...args: any) { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); - } - return target[prop].apply(target, [...args]); - }; - } + // if (prop === 'onRequest' || prop === 'onNotification') { + // return function (...args: any) { + // if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { + // window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + // } + // return target[prop].apply(target, [...args]); + // }; + // } return target[prop]; }, }); From 78a5f54e20bbbc19672e9dd3262b7fc6e2b41aa2 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 9 Jul 2022 14:03:23 +0800 Subject: [PATCH 04/24] =?UTF-8?q?refactor:=20=E9=85=8D=E5=90=88opensumi-de?= =?UTF-8?q?vtools=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=80=E6=B3=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/connection/src/common/message.ts | 10 ++++---- packages/connection/src/common/proxy.ts | 28 +++++++++++++++-------- packages/connection/src/node/connect.ts | 8 +++---- tools/electron/src/main/index.ts | 6 ++--- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/packages/connection/src/common/message.ts b/packages/connection/src/common/message.ts index 20773139fd..a31eb24f79 100644 --- a/packages/connection/src/common/message.ts +++ b/packages/connection/src/common/message.ts @@ -85,7 +85,7 @@ export class WebSocketMessageWriter extends AbstractMessageWriter implements Mes declare global { interface Window { - __OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__: any; + __opensumi_devtools: any; } } @@ -108,8 +108,8 @@ export function createWebSocketConnection(socket: any) { if (prop === 'sendRequest' || prop === 'sendNotification') { return function (...args: any) { // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.send([prop, ...args]); + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + window.__opensumi_devtools.capture([prop, ...args]); } return target[prop].apply(target, [...args]); }; @@ -118,8 +118,8 @@ export function createWebSocketConnection(socket: any) { // onNotification很多的,onRequest我都试不出来 // if (prop === 'onRequest' || prop === 'onNotification') { // return function (...args: any) { - // if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - // window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + // if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + // window.__opensumi_devtools.capture([prop, ...args]); // } // return target[prop].apply(target, [...args]); // }; diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index de97832547..61bf72962a 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -126,13 +126,21 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['错误', error]); + if ( + typeof window !== 'undefined' && + window.__opensumi_devtools && + window.__opensumi_devtools.capture + ) { + window.__opensumi_devtools.capture(['错误', error]); } reject(error); } else { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['requestResult', result.data]); + if ( + typeof window !== 'undefined' && + window.__opensumi_devtools && + window.__opensumi_devtools.capture + ) { + window.__opensumi_devtools.capture(['requestResult', result.data]); } resolve(result.data); } @@ -170,16 +178,16 @@ export class RPCProxy { if (method.startsWith('on')) { connection.onNotification(method, (...args) => this.onNotification(method, ...args)); connection.onNotification(method, (...args) => { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['onNotification', method, ...args]); + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + window.__opensumi_devtools.capture(['onNotification', method, ...args]); } this.onNotification(method, ...args); }); } else { // connection.onRequest(method, (...args) => this.onRequest(method, ...args)); connection.onRequest(method, (...args) => { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(['onRequest', method, ...args]); + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + window.__opensumi_devtools.capture(['onRequest', method, ...args]); } return this.onRequest(method, ...args); }); @@ -192,8 +200,8 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive(`onRequest: ${method} is not registered!`); + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + window.__opensumi_devtools.capture(`onRequest: ${method} is not registered!`); } return { data: NOTREGISTERMETHOD, diff --git a/packages/connection/src/node/connect.ts b/packages/connection/src/node/connect.ts index e1661813e2..e3716739fe 100644 --- a/packages/connection/src/node/connect.ts +++ b/packages/connection/src/node/connect.ts @@ -16,8 +16,8 @@ export function createSocketConnection(socket: net.Socket) { if (prop === 'sendRequest' || prop === 'sendNotification') { return function (...args: any) { // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.send([prop, ...args]); + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + window.__opensumi_devtools.capture([prop, ...args]); } return target[prop].apply(target, [...args]); }; @@ -25,8 +25,8 @@ export function createSocketConnection(socket: net.Socket) { // if (prop === 'onRequest' || prop === 'onNotification') { // return function (...args: any) { - // if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__) { - // window.__OPENSUMI_DEVTOOL_EVENT_SOURCE_TOKEN__.traffic.receive([prop, ...args]); + // if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + // window.__opensumi_devtools.capture([prop, ...args]); // } // return target[prop].apply(target, [...args]); // }; diff --git a/tools/electron/src/main/index.ts b/tools/electron/src/main/index.ts index cf620013b2..98424ce846 100644 --- a/tools/electron/src/main/index.ts +++ b/tools/electron/src/main/index.ts @@ -32,9 +32,9 @@ const electronApp = new ElectronMainApp({ electronApp.init().then(() => { electronApp.loadWorkspace(); - // const devtronPath = join(require('os').homedir(), 'Projects/ASOC2022/devtron'); - // session.defaultSession.loadExtension(devtronPath); + const devtronPath = join(require('os').homedir(), 'Projects/ASOC2022/devtron'); + session.defaultSession.loadExtension(devtronPath); - const opensumicrxPath = join(require('os').homedir(), 'Projects/ASOC2022/opensumi/opensumi-crx/build'); + const opensumicrxPath = join(require('os').homedir(), 'Projects/ASOC2022/opensumi/opensumi-devtools/build'); session.defaultSession.loadExtension(opensumicrxPath); }); From ab054dcbea2f2c7f157a1fdf7fba9fecc7a9eba8 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 9 Jul 2022 16:42:06 +0800 Subject: [PATCH 05/24] =?UTF-8?q?refactor:=20=E5=8F=AA=E5=9C=A8common/prox?= =?UTF-8?q?y.ts=E6=B3=A8=E5=B0=84capturer=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/connection/src/common/message.ts | 41 +---------------------- packages/connection/src/common/proxy.ts | 36 ++++++-------------- packages/connection/src/common/utils.ts | 13 +++++++ packages/connection/src/node/connect.ts | 30 +---------------- 4 files changed, 26 insertions(+), 94 deletions(-) diff --git a/packages/connection/src/common/message.ts b/packages/connection/src/common/message.ts index a31eb24f79..a68c297b5e 100644 --- a/packages/connection/src/common/message.ts +++ b/packages/connection/src/common/message.ts @@ -83,50 +83,11 @@ export class WebSocketMessageWriter extends AbstractMessageWriter implements Mes public end(): void {} } -declare global { - interface Window { - __opensumi_devtools: any; - } -} - /** * 给服务端的 WebSocket 及 Browser 端的 WebSocket 实例共用的方法 * @param socket * @returns */ export function createWebSocketConnection(socket: any) { - // return createMessageConnection(new WebSocketMessageReader(socket), new WebSocketMessageWriter(socket)); - - const messageConnection = createMessageConnection( - new WebSocketMessageReader(socket), - new WebSocketMessageWriter(socket), - ); - - // sendRequest是有回复的,在proxy.ts中处理requestResult - const messageConnectionProxy = new Proxy(messageConnection, { - get(target, prop) { - if (prop === 'sendRequest' || prop === 'sendNotification') { - return function (...args: any) { - // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - window.__opensumi_devtools.capture([prop, ...args]); - } - return target[prop].apply(target, [...args]); - }; - } - - // onNotification很多的,onRequest我都试不出来 - // if (prop === 'onRequest' || prop === 'onNotification') { - // return function (...args: any) { - // if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - // window.__opensumi_devtools.capture([prop, ...args]); - // } - // return target[prop].apply(target, [...args]); - // }; - // } - return target[prop]; - }, - }); - - return messageConnectionProxy; + return createMessageConnection(new WebSocketMessageReader(socket), new WebSocketMessageWriter(socket)); } diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 61bf72962a..8120bf6d18 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -1,6 +1,8 @@ import { ApplicationError } from '@opensumi/ide-core-common'; import type { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection'; +import { getCapturer } from './utils'; + export abstract class RPCService { rpcClient?: T[]; rpcRegistered?: boolean; @@ -98,8 +100,10 @@ export class RPCProxy { if (prop.startsWith('on')) { if (isSingleArray) { connection.sendNotification(prop, [...args]); + getCapturer() && getCapturer()(['sendNotification', prop, [...args]]); } else { connection.sendNotification(prop, ...args); + getCapturer() && getCapturer()(['sendNotification', prop, ...args]); } resolve(null); @@ -107,8 +111,10 @@ export class RPCProxy { let requestResult: Promise; if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; + getCapturer() && getCapturer()(['sendRequest', prop, [...args]]); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; + getCapturer() && getCapturer()(['sendRequest', prop, ...args]); } requestResult @@ -126,22 +132,10 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - if ( - typeof window !== 'undefined' && - window.__opensumi_devtools && - window.__opensumi_devtools.capture - ) { - window.__opensumi_devtools.capture(['错误', error]); - } + getCapturer() && getCapturer()(['错误', error]); reject(error); } else { - if ( - typeof window !== 'undefined' && - window.__opensumi_devtools && - window.__opensumi_devtools.capture - ) { - window.__opensumi_devtools.capture(['requestResult', result.data]); - } + getCapturer() && getCapturer()(['requestResult', result.data]); resolve(result.data); } }); @@ -176,19 +170,13 @@ export class RPCProxy { const methods = this.getServiceMethod(service); methods.forEach((method) => { if (method.startsWith('on')) { - connection.onNotification(method, (...args) => this.onNotification(method, ...args)); connection.onNotification(method, (...args) => { - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - window.__opensumi_devtools.capture(['onNotification', method, ...args]); - } + getCapturer() && getCapturer()(['onNotification', method, ...args]); this.onNotification(method, ...args); }); } else { - // connection.onRequest(method, (...args) => this.onRequest(method, ...args)); connection.onRequest(method, (...args) => { - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - window.__opensumi_devtools.capture(['onRequest', method, ...args]); - } + getCapturer() && getCapturer()(['onRequest', method, ...args]); return this.onRequest(method, ...args); }); } @@ -200,9 +188,7 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - window.__opensumi_devtools.capture(`onRequest: ${method} is not registered!`); - } + getCapturer() && getCapturer()(`onRequest: ${method} is not registered!`); return { data: NOTREGISTERMETHOD, }; diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 91d1405015..f3b0a4d2fa 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -5,3 +5,16 @@ export function stringify(obj: any): string { export function parse(input: string, reviver?: (this: any, key: string, value: any) => any): any { return JSON.parse(input, reviver); } + +declare global { + interface Window { + __opensumi_devtools: any; + } +} + +export function getCapturer() { + if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { + return window.__opensumi_devtools.capture; + } + return; +} diff --git a/packages/connection/src/node/connect.ts b/packages/connection/src/node/connect.ts index e3716739fe..683eec5064 100644 --- a/packages/connection/src/node/connect.ts +++ b/packages/connection/src/node/connect.ts @@ -7,33 +7,5 @@ import { } from '@opensumi/vscode-jsonrpc/lib/node/main'; export function createSocketConnection(socket: net.Socket) { - // return createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); - - const messageConnection = createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); - - const messageConnectionProxy = new Proxy(messageConnection, { - get(target, prop) { - if (prop === 'sendRequest' || prop === 'sendNotification') { - return function (...args: any) { - // 注意这是common/xxx,所以要同时考虑在browser和在node的情况,node是没有window的 - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - window.__opensumi_devtools.capture([prop, ...args]); - } - return target[prop].apply(target, [...args]); - }; - } - - // if (prop === 'onRequest' || prop === 'onNotification') { - // return function (...args: any) { - // if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - // window.__opensumi_devtools.capture([prop, ...args]); - // } - // return target[prop].apply(target, [...args]); - // }; - // } - return target[prop]; - }, - }); - - return messageConnectionProxy; + return createMessageConnection(new SocketMessageReader(socket), new SocketMessageWriter(socket)); } From 67d45e966068c4e027345a402689f0332071c565 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 9 Jul 2022 17:15:50 +0800 Subject: [PATCH 06/24] feat: add requestId to associate request and requestResult --- packages/connection/src/common/proxy.ts | 13 ++++++++----- packages/connection/src/common/utils.ts | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 8120bf6d18..c35916900c 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -1,7 +1,7 @@ import { ApplicationError } from '@opensumi/ide-core-common'; import type { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection'; -import { getCapturer } from './utils'; +import { getCapturer, genrateUniqueId } from './utils'; export abstract class RPCService { rpcClient?: T[]; @@ -109,12 +109,15 @@ export class RPCProxy { resolve(null); } else { let requestResult: Promise; + // generate a unique requestId to associate request and requestResult + const requestId = genrateUniqueId(); + if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; - getCapturer() && getCapturer()(['sendRequest', prop, [...args]]); + getCapturer() && getCapturer()(['sendRequest', requestId, prop, [...args]]); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; - getCapturer() && getCapturer()(['sendRequest', prop, ...args]); + getCapturer() && getCapturer()(['sendRequest', requestId, prop, ...args]); } requestResult @@ -132,10 +135,10 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - getCapturer() && getCapturer()(['错误', error]); + getCapturer() && getCapturer()(['错误', requestId, error]); reject(error); } else { - getCapturer() && getCapturer()(['requestResult', result.data]); + getCapturer() && getCapturer()(['requestResult', requestId, result.data]); resolve(result.data); } }); diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index f3b0a4d2fa..1be6aec523 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -18,3 +18,7 @@ export function getCapturer() { } return; } + +export function genrateUniqueId() { + return Date.now().toString(36) + Math.random().toString(36).substr(2); +} From 11372637d7a53dc783714eba46ebbf6bd68f3b8f Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Tue, 26 Jul 2022 18:08:21 +0800 Subject: [PATCH 07/24] refactor: new message body when capturing --- packages/connection/src/common/proxy.ts | 68 +++++++++++++++++++++---- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index c35916900c..17de5c7445 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -100,10 +100,20 @@ export class RPCProxy { if (prop.startsWith('on')) { if (isSingleArray) { connection.sendNotification(prop, [...args]); - getCapturer() && getCapturer()(['sendNotification', prop, [...args]]); + getCapturer() && + getCapturer()({ + type: 'sendNotification', + serviceMethod: prop, + arguments: args, + }); } else { connection.sendNotification(prop, ...args); - getCapturer() && getCapturer()(['sendNotification', prop, ...args]); + getCapturer() && + getCapturer()({ + type: 'sendNotification', + serviceMethod: prop, + arguments: args, + }); } resolve(null); @@ -114,10 +124,22 @@ export class RPCProxy { if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; - getCapturer() && getCapturer()(['sendRequest', requestId, prop, [...args]]); + getCapturer() && + getCapturer()({ + type: 'sendRequest', + requestId, + serviceMethod: prop, + arguments: args, + }); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; - getCapturer() && getCapturer()(['sendRequest', requestId, prop, ...args]); + getCapturer() && + getCapturer()({ + type: 'sendRequest', + requestId, + serviceMethod: prop, + arguments: args, + }); } requestResult @@ -135,10 +157,22 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - getCapturer() && getCapturer()(['错误', requestId, error]); + getCapturer() && + getCapturer()({ + type: 'requestResult', + status: 'fail', + requestId, + error, + }); reject(error); } else { - getCapturer() && getCapturer()(['requestResult', requestId, result.data]); + getCapturer() && + getCapturer()({ + type: 'requestResult', + status: 'success', + requestId, + data: result.data, + }); resolve(result.data); } }); @@ -174,12 +208,23 @@ export class RPCProxy { methods.forEach((method) => { if (method.startsWith('on')) { connection.onNotification(method, (...args) => { - getCapturer() && getCapturer()(['onNotification', method, ...args]); + getCapturer() && + getCapturer()({ + type: 'onNotification', + serviceMethod: method, + arguments: args, + }); this.onNotification(method, ...args); }); } else { connection.onRequest(method, (...args) => { - getCapturer() && getCapturer()(['onRequest', method, ...args]); + getCapturer() && + getCapturer()({ + type: 'onRequest', + status: 'success', + serviceMethod: method, + arguments: args, + }); return this.onRequest(method, ...args); }); } @@ -191,7 +236,12 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { - getCapturer() && getCapturer()(`onRequest: ${method} is not registered!`); + getCapturer() && + getCapturer()({ + type: 'onRequest', + status: 'fail', + serviceMethod: method, + }); return { data: NOTREGISTERMETHOD, }; From b8ddfca821fac060009b8f9f3376cfab2350672b Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 30 Jul 2022 10:03:26 +0800 Subject: [PATCH 08/24] fix: typo --- packages/connection/src/common/proxy.ts | 4 ++-- packages/connection/src/common/utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 17de5c7445..0965c1bedd 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -1,7 +1,7 @@ import { ApplicationError } from '@opensumi/ide-core-common'; import type { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection'; -import { getCapturer, genrateUniqueId } from './utils'; +import { getCapturer, generateUniqueId } from './utils'; export abstract class RPCService { rpcClient?: T[]; @@ -120,7 +120,7 @@ export class RPCProxy { } else { let requestResult: Promise; // generate a unique requestId to associate request and requestResult - const requestId = genrateUniqueId(); + const requestId = generateUniqueId(); if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 1be6aec523..ae3be474c7 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -19,6 +19,6 @@ export function getCapturer() { return; } -export function genrateUniqueId() { +export function generateUniqueId() { return Date.now().toString(36) + Math.random().toString(36).substr(2); } From 43193e8c2b1e9cf826a6cdbc1aeb9a4f01979823 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 30 Jul 2022 12:46:42 +0800 Subject: [PATCH 09/24] feat: capture onRequestResult --- packages/connection/src/common/proxy.ts | 48 ++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 0965c1bedd..52c15bcd63 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -162,7 +162,7 @@ export class RPCProxy { type: 'requestResult', status: 'fail', requestId, - error, + error: result.data, }); reject(error); } else { @@ -218,14 +218,39 @@ export class RPCProxy { }); } else { connection.onRequest(method, (...args) => { + // *** capturer *** + const requestId = generateUniqueId(); getCapturer() && getCapturer()({ type: 'onRequest', - status: 'success', + requestId, serviceMethod: method, arguments: args, }); - return this.onRequest(method, ...args); + // **************** + const result = this.onRequest(method, ...args); + // *** capturer *** + result + .then((result) => { + getCapturer() && + getCapturer()({ + type: 'onRequestResult', + status: 'success', + requestId, + data: result.data, + }); + }) + .catch((err) => { + getCapturer() && + getCapturer()({ + type: 'onRequestResult', + status: 'fail', + requestId, + error: err.data, + }); + }); + // **************** + return result; }); } @@ -236,15 +261,28 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { + // *** capturer *** + const requestId = generateUniqueId(); getCapturer() && getCapturer()({ type: 'onRequest', - status: 'fail', + requestId, serviceMethod: method, }); - return { + // **************** + const result = { data: NOTREGISTERMETHOD, }; + // *** capturer *** + getCapturer() && + getCapturer()({ + type: 'onRequestResult', + status: 'fail', + requestId, + error: result.data, + }); + // **************** + return result; } }); } From 1ed29f1c0cdb92279783c0a878712499317a027c Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Thu, 18 Aug 2022 11:37:04 +0800 Subject: [PATCH 10/24] refactor: join capturing code into one line --- packages/connection/src/common/proxy.ts | 114 ++++++------------------ 1 file changed, 26 insertions(+), 88 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 52c15bcd63..ea64f0ecc6 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -100,20 +100,12 @@ export class RPCProxy { if (prop.startsWith('on')) { if (isSingleArray) { connection.sendNotification(prop, [...args]); - getCapturer() && - getCapturer()({ - type: 'sendNotification', - serviceMethod: prop, - arguments: args, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'sendNotification', serviceMethod: prop, arguments: args }); } else { connection.sendNotification(prop, ...args); - getCapturer() && - getCapturer()({ - type: 'sendNotification', - serviceMethod: prop, - arguments: args, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'sendNotification', serviceMethod: prop, arguments: args }); } resolve(null); @@ -124,22 +116,12 @@ export class RPCProxy { if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; - getCapturer() && - getCapturer()({ - type: 'sendRequest', - requestId, - serviceMethod: prop, - arguments: args, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; - getCapturer() && - getCapturer()({ - type: 'sendRequest', - requestId, - serviceMethod: prop, - arguments: args, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); } requestResult @@ -157,22 +139,12 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - getCapturer() && - getCapturer()({ - type: 'requestResult', - status: 'fail', - requestId, - error: result.data, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'requestResult', status: 'fail', requestId, error: result.data }); reject(error); } else { - getCapturer() && - getCapturer()({ - type: 'requestResult', - status: 'success', - requestId, - data: result.data, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'requestResult', status: 'success', requestId, data: result.data }); resolve(result.data); } }); @@ -208,48 +180,27 @@ export class RPCProxy { methods.forEach((method) => { if (method.startsWith('on')) { connection.onNotification(method, (...args) => { - getCapturer() && - getCapturer()({ - type: 'onNotification', - serviceMethod: method, - arguments: args, - }); this.onNotification(method, ...args); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onNotification', serviceMethod: method, arguments: args }); }); } else { connection.onRequest(method, (...args) => { - // *** capturer *** const requestId = generateUniqueId(); - getCapturer() && - getCapturer()({ - type: 'onRequest', - requestId, - serviceMethod: method, - arguments: args, - }); - // **************** const result = this.onRequest(method, ...args); - // *** capturer *** + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onRequest', requestId, serviceMethod: method, arguments: args }); + result .then((result) => { - getCapturer() && - getCapturer()({ - type: 'onRequestResult', - status: 'success', - requestId, - data: result.data, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'success', requestId, data: result.data }); }) .catch((err) => { - getCapturer() && - getCapturer()({ - type: 'onRequestResult', - status: 'fail', - requestId, - error: err.data, - }); + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, error: err.data }); }); - // **************** + return result; }); } @@ -261,27 +212,14 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { - // *** capturer *** const requestId = generateUniqueId(); - getCapturer() && - getCapturer()({ - type: 'onRequest', - requestId, - serviceMethod: method, - }); - // **************** + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onRequest', requestId, serviceMethod: method }); const result = { data: NOTREGISTERMETHOD, }; - // *** capturer *** - getCapturer() && - getCapturer()({ - type: 'onRequestResult', - status: 'fail', - requestId, - error: result.data, - }); - // **************** + // prettier-ignore + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, error: result.data }); return result; } }); From 6bc41619eb6e2fe50e777dcdfb776c1b54c50abf Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Thu, 18 Aug 2022 18:13:04 +0800 Subject: [PATCH 11/24] refactor: capture serviceMethod property for all messages --- packages/connection/src/common/proxy.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index ea64f0ecc6..3729772bd5 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -140,11 +140,11 @@ export class RPCProxy { error.cause = applicationError; } // prettier-ignore - getCapturer() && getCapturer()({ type: 'requestResult', status: 'fail', requestId, error: result.data }); + getCapturer() && getCapturer()({ type: 'requestResult', status: 'fail', requestId, serviceMethod: prop, error: result.data }); reject(error); } else { // prettier-ignore - getCapturer() && getCapturer()({ type: 'requestResult', status: 'success', requestId, data: result.data }); + getCapturer() && getCapturer()({ type: 'requestResult', status: 'success', requestId, serviceMethod: prop, data: result.data }); resolve(result.data); } }); @@ -194,11 +194,11 @@ export class RPCProxy { result .then((result) => { // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'success', requestId, data: result.data }); + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'success', requestId, serviceMethod: method, data: result.data }); }) .catch((err) => { // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, error: err.data }); + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, serviceMethod: method, error: err.data }); }); return result; @@ -219,7 +219,7 @@ export class RPCProxy { data: NOTREGISTERMETHOD, }; // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, error: result.data }); + getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, serviceMethod: method, error: result.data }); return result; } }); From f4fe5bddd50ccdb91243bffc3352c7a62c9f3140 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Thu, 18 Aug 2022 18:33:45 +0800 Subject: [PATCH 12/24] feat: a contribution for opensumi devtools to measure network latency --- .../browser/chrome-devtools.contribution.ts | 45 +++++++++++++++++++ .../browser/connection-rtt-contribution.ts | 16 +------ .../src/browser/connection-rtt-service.ts | 15 +++++++ packages/addons/src/browser/index.ts | 9 ++-- 4 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 packages/addons/src/browser/chrome-devtools.contribution.ts create mode 100644 packages/addons/src/browser/connection-rtt-service.ts diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts new file mode 100644 index 0000000000..7d0f1ffb27 --- /dev/null +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -0,0 +1,45 @@ +import { Autowired } from '@opensumi/di'; +import { ClientAppContribution } from '@opensumi/ide-core-browser'; +import { Domain } from '@opensumi/ide-core-common/lib/di-helper'; + +import { ConnectionRTTBrowserServiceToken, ConnectionRTTBrowserService } from './connection-rtt-service'; + +@Domain(ClientAppContribution) +export class ChromeDevtoolsContribution implements ClientAppContribution { + @Autowired(ConnectionRTTBrowserServiceToken) + protected readonly rttService: ConnectionRTTBrowserService; + + private interval?: NodeJS.Timeout; + + static INTERVAL = 1000; + + // start and keep polling for the states of opensumi devtools + initialize() { + global.setInterval(() => { + // if devtools is in capturing state, rtt should be measured and + // will be presented as network latency in opensumi devtools + if (window.__opensumi_devtools && window.__opensumi_devtools.capture) { + if (!this.interval) { + this.startRTTInterval(); + } + } else { + if (this.interval) { + global.clearInterval(this.interval); + this.interval = undefined; + } + } + }, 1000); + } + + private startRTTInterval() { + this.interval = global.setInterval(async () => { + const start = Date.now(); + await this.rttService.measure(); + const rtt = Date.now() - start; + // "if" below is to prevent setting latency after stoping capturing + if (window.__opensumi_devtools.capture) { + window.__opensumi_devtools.latency = rtt; + } + }, ChromeDevtoolsContribution.INTERVAL); + } +} diff --git a/packages/addons/src/browser/connection-rtt-contribution.ts b/packages/addons/src/browser/connection-rtt-contribution.ts index 798ecb8bf7..5ed8f6f1c5 100644 --- a/packages/addons/src/browser/connection-rtt-contribution.ts +++ b/packages/addons/src/browser/connection-rtt-contribution.ts @@ -1,10 +1,10 @@ -import { Autowired, Injectable } from '@opensumi/di'; +import { Autowired } from '@opensumi/di'; import { IStatusBarService, StatusBarAlignment, StatusBarEntryAccessor } from '@opensumi/ide-core-browser/lib/services'; import { Command, CommandContribution, CommandRegistry } from '@opensumi/ide-core-common/lib/command'; import { Domain } from '@opensumi/ide-core-common/lib/di-helper'; import { localize } from '@opensumi/ide-core-common/lib/localize'; -import { ConnectionBackServicePath, IConnectionBackService } from '../common'; +import { ConnectionRTTBrowserServiceToken, ConnectionRTTBrowserService } from './connection-rtt-service'; const START_CONNECTION_RTT_COMMAND: Command = { id: 'connection.start.rtt', @@ -23,18 +23,6 @@ const statusBarOption = { priority: Infinity - 1, }; -export const ConnectionRTTBrowserServiceToken = Symbol('ConnectionRTTBrowserService'); - -@Injectable() -export class ConnectionRTTBrowserService { - @Autowired(ConnectionBackServicePath) - protected readonly connectionBackService: IConnectionBackService; - - async measure() { - await this.connectionBackService.$measure(); - } -} - @Domain(CommandContribution) export class ConnectionRTTContribution implements CommandContribution { @Autowired(IStatusBarService) diff --git a/packages/addons/src/browser/connection-rtt-service.ts b/packages/addons/src/browser/connection-rtt-service.ts new file mode 100644 index 0000000000..6625dc0e83 --- /dev/null +++ b/packages/addons/src/browser/connection-rtt-service.ts @@ -0,0 +1,15 @@ +import { Autowired, Injectable } from '@opensumi/di'; + +import { ConnectionBackServicePath, IConnectionBackService } from '../common'; + +export const ConnectionRTTBrowserServiceToken = Symbol('ConnectionRTTBrowserService'); + +@Injectable() +export class ConnectionRTTBrowserService { + @Autowired(ConnectionBackServicePath) + protected readonly connectionBackService: IConnectionBackService; + + async measure() { + await this.connectionBackService.$measure(); + } +} diff --git a/packages/addons/src/browser/index.ts b/packages/addons/src/browser/index.ts index acb3e8bddf..a3e2b20111 100644 --- a/packages/addons/src/browser/index.ts +++ b/packages/addons/src/browser/index.ts @@ -3,11 +3,9 @@ import { BrowserModule } from '@opensumi/ide-core-browser'; import { IFileDropFrontendServiceToken, FileDropServicePath, ConnectionBackServicePath } from '../common'; -import { - ConnectionRTTBrowserService, - ConnectionRTTBrowserServiceToken, - ConnectionRTTContribution, -} from './connection-rtt-contribution'; +import { ChromeDevtoolsContribution } from './chrome-devtools.contribution'; +import { ConnectionRTTContribution } from './connection-rtt-contribution'; +import { ConnectionRTTBrowserService, ConnectionRTTBrowserServiceToken } from './connection-rtt-service'; import { FileDropContribution } from './file-drop.contribution'; import { FileDropService } from './file-drop.service'; import { FileSearchContribution } from './file-search.contribution'; @@ -18,6 +16,7 @@ import { ToolbarCustomizeContribution } from './toolbar-customize/toolbar-custom @Injectable() export class ClientAddonModule extends BrowserModule { providers = [ + ChromeDevtoolsContribution, LanguageChangeHintContribution, FileSearchContribution, StatusBarContribution, From 26051e5c7dc9e1c05b762420d3fc47e520efe0d7 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Sat, 20 Aug 2022 15:36:24 +0800 Subject: [PATCH 13/24] feat: expose a global to communicate with opensumi devtools --- .../addons/src/browser/chrome-devtools.contribution.ts | 8 ++++---- packages/connection/src/common/utils.ts | 6 +++--- packages/core-browser/src/bootstrap/app.ts | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts index 7d0f1ffb27..248f3a1463 100644 --- a/packages/addons/src/browser/chrome-devtools.contribution.ts +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -13,12 +13,12 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { static INTERVAL = 1000; - // start and keep polling for the states of opensumi devtools initialize() { + // keep polling for the states of opensumi devtools global.setInterval(() => { // if devtools is in capturing state, rtt should be measured and // will be presented as network latency in opensumi devtools - if (window.__opensumi_devtools && window.__opensumi_devtools.capture) { + if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { if (!this.interval) { this.startRTTInterval(); } @@ -37,8 +37,8 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { await this.rttService.measure(); const rtt = Date.now() - start; // "if" below is to prevent setting latency after stoping capturing - if (window.__opensumi_devtools.capture) { - window.__opensumi_devtools.latency = rtt; + if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.latency = rtt; } }, ChromeDevtoolsContribution.INTERVAL); } diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index ae3be474c7..f2d9b634f7 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -8,13 +8,13 @@ export function parse(input: string, reviver?: (this: any, key: string, value: a declare global { interface Window { - __opensumi_devtools: any; + __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; } } export function getCapturer() { - if (typeof window !== 'undefined' && window.__opensumi_devtools && window.__opensumi_devtools.capture) { - return window.__opensumi_devtools.capture; + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + return window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture; } return; } diff --git a/packages/core-browser/src/bootstrap/app.ts b/packages/core-browser/src/bootstrap/app.ts index 67b0728442..8a3589977a 100644 --- a/packages/core-browser/src/bootstrap/app.ts +++ b/packages/core-browser/src/bootstrap/app.ts @@ -146,6 +146,10 @@ export class ClientApp implements IClientApp, IDisposable { stateService: ClientAppStateService; constructor(opts: IClientAppOpts) { + // set a global so the opensumi devtools can identify that + // the current page is powered by opensumi core + window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ = {}; + const { modules, contributions, From 9f895f210a0eeb285f90ef6f7339bde7c67e65d5 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 22 Aug 2022 11:07:45 +0800 Subject: [PATCH 14/24] build: global.d.ts not work --- packages/connection/src/common/utils.ts | 6 ------ typings/global.d.ts | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index f2d9b634f7..34d03671d8 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -6,12 +6,6 @@ export function parse(input: string, reviver?: (this: any, key: string, value: a return JSON.parse(input, reviver); } -declare global { - interface Window { - __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; - } -} - export function getCapturer() { if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { return window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture; diff --git a/typings/global.d.ts b/typings/global.d.ts index c325fa013b..2fdcad785b 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -30,6 +30,10 @@ declare global { unobserve(target: Element): void; disconnect(): void; } + + interface Window { + __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; + } } declare var ResizeObserver: { From d98bb785c909f408258abe5f37a154e7b479acbe Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 22 Aug 2022 12:33:11 +0800 Subject: [PATCH 15/24] fix: global.d.ts syntax error --- typings/global.d.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/typings/global.d.ts b/typings/global.d.ts index 2fdcad785b..f835ace623 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -14,26 +14,13 @@ interface DOMRectReadOnly { readonly left: number; } -declare global { - interface ResizeObserverCallback { - (entries: ResizeObserverEntry[], observer: ResizeObserver): void - } - - interface ResizeObserverEntry { - readonly target: Element; - readonly contentRect: DOMRectReadOnly; - } - - class ResizeObserver { - constructor(callback: ResizeObserverCallback); - observe(target: Element): void; - unobserve(target: Element): void; - disconnect(): void; - } +interface ResizeObserverCallback { + (entries: ResizeObserverEntry[], observer: ResizeObserver): void +} - interface Window { - __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; - } +interface ResizeObserverEntry { + readonly target: Element; + readonly contentRect: DOMRectReadOnly; } declare var ResizeObserver: { @@ -47,4 +34,6 @@ interface ResizeObserver { disconnect(): void; } -export default ResizeObserver; +interface Window { + __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; +} From 437c1d49918cabbd883684eb956814788e603389 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 22 Aug 2022 12:45:48 +0800 Subject: [PATCH 16/24] chore: remove loadExtension code from electron --- tools/electron/src/main/index.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tools/electron/src/main/index.ts b/tools/electron/src/main/index.ts index 98424ce846..537f95710f 100644 --- a/tools/electron/src/main/index.ts +++ b/tools/electron/src/main/index.ts @@ -1,6 +1,6 @@ import { join } from 'path'; -import { app, session } from 'electron'; +import { app } from 'electron'; import { URI } from '@opensumi/ide-core-common'; import { ElectronMainApp } from '@opensumi/ide-core-electron-main'; @@ -31,10 +31,4 @@ const electronApp = new ElectronMainApp({ electronApp.init().then(() => { electronApp.loadWorkspace(); - - const devtronPath = join(require('os').homedir(), 'Projects/ASOC2022/devtron'); - session.defaultSession.loadExtension(devtronPath); - - const opensumicrxPath = join(require('os').homedir(), 'Projects/ASOC2022/opensumi/opensumi-devtools/build'); - session.defaultSession.loadExtension(opensumicrxPath); }); From 0fe0caefc3b01a803b66d25c77d18bde4fa5bbbc Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 22 Aug 2022 16:25:11 +0800 Subject: [PATCH 17/24] fix: declare in global.d.ts will not work --- packages/connection/src/common/utils.ts | 6 ++++++ typings/global.d.ts | 25 ++++++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 34d03671d8..3daf69e444 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -1,3 +1,9 @@ +declare global { + interface Window { + __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; + } +} + export function stringify(obj: any): string { return JSON.stringify(obj); } diff --git a/typings/global.d.ts b/typings/global.d.ts index f835ace623..c325fa013b 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -14,13 +14,22 @@ interface DOMRectReadOnly { readonly left: number; } -interface ResizeObserverCallback { - (entries: ResizeObserverEntry[], observer: ResizeObserver): void -} +declare global { + interface ResizeObserverCallback { + (entries: ResizeObserverEntry[], observer: ResizeObserver): void + } + + interface ResizeObserverEntry { + readonly target: Element; + readonly contentRect: DOMRectReadOnly; + } -interface ResizeObserverEntry { - readonly target: Element; - readonly contentRect: DOMRectReadOnly; + class ResizeObserver { + constructor(callback: ResizeObserverCallback); + observe(target: Element): void; + unobserve(target: Element): void; + disconnect(): void; + } } declare var ResizeObserver: { @@ -34,6 +43,4 @@ interface ResizeObserver { disconnect(): void; } -interface Window { - __OPENSUMI_DEVTOOLS_GLOBAL_HOOK__: any; -} +export default ResizeObserver; From aab407af18330cfb5befa543bc341abac6d18633 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Mon, 22 Aug 2022 17:10:07 +0800 Subject: [PATCH 18/24] fix: devtools global hook actually not defined when in test --- packages/addons/src/browser/chrome-devtools.contribution.ts | 2 +- packages/connection/src/common/utils.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts index 248f3a1463..41cafde1c6 100644 --- a/packages/addons/src/browser/chrome-devtools.contribution.ts +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -18,7 +18,7 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { global.setInterval(() => { // if devtools is in capturing state, rtt should be measured and // will be presented as network latency in opensumi devtools - if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { if (!this.interval) { this.startRTTInterval(); } diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 3daf69e444..61e373c879 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -13,7 +13,11 @@ export function parse(input: string, reviver?: (this: any, key: string, value: a } export function getCapturer() { - if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + if ( + typeof window !== 'undefined' && + window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && + window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture + ) { return window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture; } return; From 07d6fefb321bebc45c9f14284290bd10dd87e76f Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 08:41:44 +0800 Subject: [PATCH 19/24] refactor: messages capture code --- packages/connection/src/common/proxy.ts | 73 +++++++++++++++++-------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 3729772bd5..b511734d5c 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -48,6 +48,13 @@ export class RPCProxy { private connection: MessageConnection; private proxyService: any = {}; private logger: any; + // capture messages for opensumi devtools + private capture(message: any): void { + const capturer = getCapturer(); + if (capturer !== undefined) { + capturer(message); + } + } constructor(public target?: RPCService, logger?: any) { this.waitForConnection(); @@ -100,12 +107,10 @@ export class RPCProxy { if (prop.startsWith('on')) { if (isSingleArray) { connection.sendNotification(prop, [...args]); - // prettier-ignore - getCapturer() && getCapturer()({ type: 'sendNotification', serviceMethod: prop, arguments: args }); + this.capture({ type: 'sendNotification', serviceMethod: prop, arguments: args }); } else { connection.sendNotification(prop, ...args); - // prettier-ignore - getCapturer() && getCapturer()({ type: 'sendNotification', serviceMethod: prop, arguments: args }); + this.capture({ type: 'sendNotification', serviceMethod: prop, arguments: args }); } resolve(null); @@ -116,12 +121,10 @@ export class RPCProxy { if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; - // prettier-ignore - getCapturer() && getCapturer()({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); + this.capture({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; - // prettier-ignore - getCapturer() && getCapturer()({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); + this.capture({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); } requestResult @@ -139,12 +142,22 @@ export class RPCProxy { const applicationError = ApplicationError.fromJson(result.error.code, result.error.data); error.cause = applicationError; } - // prettier-ignore - getCapturer() && getCapturer()({ type: 'requestResult', status: 'fail', requestId, serviceMethod: prop, error: result.data }); + this.capture({ + type: 'requestResult', + status: 'fail', + requestId, + serviceMethod: prop, + error: result.data, + }); reject(error); } else { - // prettier-ignore - getCapturer() && getCapturer()({ type: 'requestResult', status: 'success', requestId, serviceMethod: prop, data: result.data }); + this.capture({ + type: 'requestResult', + status: 'success', + requestId, + serviceMethod: prop, + data: result.data, + }); resolve(result.data); } }); @@ -181,24 +194,32 @@ export class RPCProxy { if (method.startsWith('on')) { connection.onNotification(method, (...args) => { this.onNotification(method, ...args); - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onNotification', serviceMethod: method, arguments: args }); + this.capture({ type: 'onNotification', serviceMethod: method, arguments: args }); }); } else { connection.onRequest(method, (...args) => { const requestId = generateUniqueId(); const result = this.onRequest(method, ...args); - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequest', requestId, serviceMethod: method, arguments: args }); + this.capture({ type: 'onRequest', requestId, serviceMethod: method, arguments: args }); result .then((result) => { - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'success', requestId, serviceMethod: method, data: result.data }); + this.capture({ + type: 'onRequestResult', + status: 'success', + requestId, + serviceMethod: method, + data: result.data, + }); }) .catch((err) => { - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, serviceMethod: method, error: err.data }); + this.capture({ + type: 'onRequestResult', + status: 'fail', + requestId, + serviceMethod: method, + error: err.data, + }); }); return result; @@ -213,13 +234,17 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { const requestId = generateUniqueId(); - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequest', requestId, serviceMethod: method }); + this.capture({ type: 'onRequest', requestId, serviceMethod: method }); const result = { data: NOTREGISTERMETHOD, }; - // prettier-ignore - getCapturer() && getCapturer()({ type: 'onRequestResult', status: 'fail', requestId, serviceMethod: method, error: result.data }); + this.capture({ + type: 'onRequestResult', + status: 'fail', + requestId, + serviceMethod: method, + error: result.data, + }); return result; } }); From 8e8ca96524e8da83176f64db45c7c155283c3080 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 09:24:26 +0800 Subject: [PATCH 20/24] refactor: types support --- packages/connection/src/common/proxy.ts | 38 ++++++++++++------------- packages/connection/src/common/utils.ts | 24 ++++++++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index b511734d5c..83e4ca5f68 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -1,7 +1,7 @@ import { ApplicationError } from '@opensumi/ide-core-common'; import type { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection'; -import { getCapturer, generateUniqueId } from './utils'; +import { MessageType, ResponseStatus, ICapturedMessage, getCapturer, generateUniqueId } from './utils'; export abstract class RPCService { rpcClient?: T[]; @@ -49,7 +49,7 @@ export class RPCProxy { private proxyService: any = {}; private logger: any; // capture messages for opensumi devtools - private capture(message: any): void { + private capture(message: ICapturedMessage): void { const capturer = getCapturer(); if (capturer !== undefined) { capturer(message); @@ -107,10 +107,10 @@ export class RPCProxy { if (prop.startsWith('on')) { if (isSingleArray) { connection.sendNotification(prop, [...args]); - this.capture({ type: 'sendNotification', serviceMethod: prop, arguments: args }); + this.capture({ type: MessageType.SendNotification, serviceMethod: prop, arguments: args }); } else { connection.sendNotification(prop, ...args); - this.capture({ type: 'sendNotification', serviceMethod: prop, arguments: args }); + this.capture({ type: MessageType.SendNotification, serviceMethod: prop, arguments: args }); } resolve(null); @@ -121,10 +121,10 @@ export class RPCProxy { if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; - this.capture({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); + this.capture({ type: MessageType.SendRequest, requestId, serviceMethod: prop, arguments: args }); } else { requestResult = connection.sendRequest(prop, ...args) as Promise; - this.capture({ type: 'sendRequest', requestId, serviceMethod: prop, arguments: args }); + this.capture({ type: MessageType.SendRequest, requestId, serviceMethod: prop, arguments: args }); } requestResult @@ -143,8 +143,8 @@ export class RPCProxy { error.cause = applicationError; } this.capture({ - type: 'requestResult', - status: 'fail', + type: MessageType.RequestResult, + status: ResponseStatus.Fail, requestId, serviceMethod: prop, error: result.data, @@ -152,8 +152,8 @@ export class RPCProxy { reject(error); } else { this.capture({ - type: 'requestResult', - status: 'success', + type: MessageType.RequestResult, + status: ResponseStatus.Success, requestId, serviceMethod: prop, data: result.data, @@ -194,19 +194,19 @@ export class RPCProxy { if (method.startsWith('on')) { connection.onNotification(method, (...args) => { this.onNotification(method, ...args); - this.capture({ type: 'onNotification', serviceMethod: method, arguments: args }); + this.capture({ type: MessageType.OnNotification, serviceMethod: method, arguments: args }); }); } else { connection.onRequest(method, (...args) => { const requestId = generateUniqueId(); const result = this.onRequest(method, ...args); - this.capture({ type: 'onRequest', requestId, serviceMethod: method, arguments: args }); + this.capture({ type: MessageType.OnRequest, requestId, serviceMethod: method, arguments: args }); result .then((result) => { this.capture({ - type: 'onRequestResult', - status: 'success', + type: MessageType.OnRequestResult, + status: ResponseStatus.Success, requestId, serviceMethod: method, data: result.data, @@ -214,8 +214,8 @@ export class RPCProxy { }) .catch((err) => { this.capture({ - type: 'onRequestResult', - status: 'fail', + type: MessageType.OnRequestResult, + status: ResponseStatus.Fail, requestId, serviceMethod: method, error: err.data, @@ -234,13 +234,13 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { const requestId = generateUniqueId(); - this.capture({ type: 'onRequest', requestId, serviceMethod: method }); + this.capture({ type: MessageType.OnRequest, requestId, serviceMethod: method }); const result = { data: NOTREGISTERMETHOD, }; this.capture({ - type: 'onRequestResult', - status: 'fail', + type: MessageType.OnRequestResult, + status: ResponseStatus.Fail, requestId, serviceMethod: method, error: result.data, diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 61e373c879..2fc13ed73d 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -4,6 +4,30 @@ declare global { } } +export enum MessageType { + SendNotification = 'sendNotification', + SendRequest = 'sendRequest', + RequestResult = 'requestResult', + OnNotification = 'onNotification', + OnRequest = 'onRequest', + OnRequestResult = 'onRequestResult', +} + +export enum ResponseStatus { + Success = 'success', + Fail = 'fail', +} + +export interface ICapturedMessage { + type: MessageType; + serviceMethod: string; + arguments?: any; + requestId?: string; + status?: ResponseStatus; + data?: any; + error?: any; +} + export function stringify(obj: any): string { return JSON.stringify(obj); } From 3b99bccef89edfa855888b6e363a004144dd27e8 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 10:27:44 +0800 Subject: [PATCH 21/24] refactor: receive notification from opensumi devtools by custom event --- .../browser/chrome-devtools.contribution.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts index 41cafde1c6..6c39807de8 100644 --- a/packages/addons/src/browser/chrome-devtools.contribution.ts +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -14,21 +14,27 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { static INTERVAL = 1000; initialize() { - // keep polling for the states of opensumi devtools - global.setInterval(() => { - // if devtools is in capturing state, rtt should be measured and - // will be presented as network latency in opensumi devtools - if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + // receive notification from opensumi devtools by custom event + window.addEventListener('devtools:latency', (event) => { + const { command } = event.detail; + if (command === 'start') { if (!this.interval) { this.startRTTInterval(); } - } else { + } else if (command === 'stop') { if (this.interval) { global.clearInterval(this.interval); this.interval = undefined; } } - }, 1000); + }); + + // if opensumi devtools has started capturing before this contribution point is registered + if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + if (!this.interval) { + this.startRTTInterval(); + } + } } private startRTTInterval() { From 245af374e0815b6a209ea712f6e346621ac66f36 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 21:46:00 +0800 Subject: [PATCH 22/24] refactor: substitute generateUniqueIda() with already available uuid() --- packages/connection/src/common/proxy.ts | 10 +++++----- packages/connection/src/common/utils.ts | 4 ---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/connection/src/common/proxy.ts b/packages/connection/src/common/proxy.ts index 83e4ca5f68..fa1d8962e9 100644 --- a/packages/connection/src/common/proxy.ts +++ b/packages/connection/src/common/proxy.ts @@ -1,7 +1,7 @@ -import { ApplicationError } from '@opensumi/ide-core-common'; +import { ApplicationError, uuid } from '@opensumi/ide-core-common'; import type { MessageConnection } from '@opensumi/vscode-jsonrpc/lib/common/connection'; -import { MessageType, ResponseStatus, ICapturedMessage, getCapturer, generateUniqueId } from './utils'; +import { MessageType, ResponseStatus, ICapturedMessage, getCapturer } from './utils'; export abstract class RPCService { rpcClient?: T[]; @@ -117,7 +117,7 @@ export class RPCProxy { } else { let requestResult: Promise; // generate a unique requestId to associate request and requestResult - const requestId = generateUniqueId(); + const requestId = uuid(); if (isSingleArray) { requestResult = connection.sendRequest(prop, [...args]) as Promise; @@ -198,7 +198,7 @@ export class RPCProxy { }); } else { connection.onRequest(method, (...args) => { - const requestId = generateUniqueId(); + const requestId = uuid(); const result = this.onRequest(method, ...args); this.capture({ type: MessageType.OnRequest, requestId, serviceMethod: method, arguments: args }); @@ -233,7 +233,7 @@ export class RPCProxy { connection.onRequest((method) => { if (!this.proxyService[method]) { - const requestId = generateUniqueId(); + const requestId = uuid(); this.capture({ type: MessageType.OnRequest, requestId, serviceMethod: method }); const result = { data: NOTREGISTERMETHOD, diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index 2fc13ed73d..aeb0b9e51b 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -46,7 +46,3 @@ export function getCapturer() { } return; } - -export function generateUniqueId() { - return Date.now().toString(36) + Math.random().toString(36).substr(2); -} From 416032b95ef94c1bd2104934ba9c52c85d66ff5d Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 21:48:31 +0800 Subject: [PATCH 23/24] refactor: shorter code with same function refactor: shorter code with same function --- packages/addons/src/browser/chrome-devtools.contribution.ts | 2 +- packages/connection/src/common/utils.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts index 6c39807de8..a8dc2a6732 100644 --- a/packages/addons/src/browser/chrome-devtools.contribution.ts +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -30,7 +30,7 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { }); // if opensumi devtools has started capturing before this contribution point is registered - if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture) { + if (window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__?.capture) { if (!this.interval) { this.startRTTInterval(); } diff --git a/packages/connection/src/common/utils.ts b/packages/connection/src/common/utils.ts index aeb0b9e51b..321715628e 100644 --- a/packages/connection/src/common/utils.ts +++ b/packages/connection/src/common/utils.ts @@ -37,11 +37,7 @@ export function parse(input: string, reviver?: (this: any, key: string, value: a } export function getCapturer() { - if ( - typeof window !== 'undefined' && - window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__ && - window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture - ) { + if (typeof window !== 'undefined' && window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__?.capture) { return window.__OPENSUMI_DEVTOOLS_GLOBAL_HOOK__.capture; } return; From 29ff6708423e6fdf302653b3f31619e7810b4e86 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Aug 2022 21:58:32 +0800 Subject: [PATCH 24/24] refactor: use enum to define all events and commands from devtools --- .../src/browser/chrome-devtools.contribution.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/addons/src/browser/chrome-devtools.contribution.ts b/packages/addons/src/browser/chrome-devtools.contribution.ts index a8dc2a6732..fb43193bea 100644 --- a/packages/addons/src/browser/chrome-devtools.contribution.ts +++ b/packages/addons/src/browser/chrome-devtools.contribution.ts @@ -4,6 +4,15 @@ import { Domain } from '@opensumi/ide-core-common/lib/di-helper'; import { ConnectionRTTBrowserServiceToken, ConnectionRTTBrowserService } from './connection-rtt-service'; +enum DevtoolsEvent { + Latency = 'devtools:latency', +} + +enum DevtoolsCommand { + Start = 'start', + Stop = 'stop', +} + @Domain(ClientAppContribution) export class ChromeDevtoolsContribution implements ClientAppContribution { @Autowired(ConnectionRTTBrowserServiceToken) @@ -15,13 +24,13 @@ export class ChromeDevtoolsContribution implements ClientAppContribution { initialize() { // receive notification from opensumi devtools by custom event - window.addEventListener('devtools:latency', (event) => { + window.addEventListener(DevtoolsEvent.Latency, (event) => { const { command } = event.detail; - if (command === 'start') { + if (command === DevtoolsCommand.Start) { if (!this.interval) { this.startRTTInterval(); } - } else if (command === 'stop') { + } else if (command === DevtoolsCommand.Stop) { if (this.interval) { global.clearInterval(this.interval); this.interval = undefined;