Browse Source

Adds optional binary serialization to ipc messages

- Improves performance on sending lots of data to the Graph
main
Eric Amodio 1 year ago
parent
commit
be50f2b3ed
15 changed files with 106 additions and 84 deletions
  1. +6
    -2
      src/plus/webviews/graph/protocol.ts
  2. +3
    -1
      src/system/logger.scope.ts
  3. +2
    -5
      src/webviews/apps/commitDetails/commitDetails.ts
  4. +2
    -6
      src/webviews/apps/home/home.ts
  5. +2
    -6
      src/webviews/apps/plus/account/account.ts
  6. +3
    -4
      src/webviews/apps/plus/focus/focus.ts
  7. +20
    -20
      src/webviews/apps/plus/graph/graph.tsx
  8. +2
    -5
      src/webviews/apps/plus/patchDetails/patchDetails.ts
  9. +2
    -6
      src/webviews/apps/plus/timeline/timeline.ts
  10. +3
    -6
      src/webviews/apps/rebase/rebase.ts
  11. +2
    -6
      src/webviews/apps/settings/settings.ts
  12. +37
    -8
      src/webviews/apps/shared/appBase.ts
  13. +2
    -6
      src/webviews/apps/welcome/welcome.ts
  14. +2
    -0
      src/webviews/protocol.ts
  15. +18
    -3
      src/webviews/webviewController.ts

+ 6
- 2
src/plus/webviews/graph/protocol.ts View File

@ -309,7 +309,7 @@ export const UpdateSelectionCommandType = new IpcCommandType
export interface DidChangeParams { export interface DidChangeParams {
state: State; state: State;
} }
export const DidChangeNotificationType = new IpcNotificationType<DidChangeParams>('graph/didChange', true);
export const DidChangeNotificationType = new IpcNotificationType<DidChangeParams>('graph/didChange', true, true);
export interface DidChangeGraphConfigurationParams { export interface DidChangeGraphConfigurationParams {
config: GraphComponentConfig; config: GraphComponentConfig;
@ -387,7 +387,11 @@ export interface DidChangeRowsParams {
rowsStatsLoading: boolean; rowsStatsLoading: boolean;
selectedRows?: GraphSelectedRows; selectedRows?: GraphSelectedRows;
} }
export const DidChangeRowsNotificationType = new IpcNotificationType<DidChangeRowsParams>('graph/rows/didChange');
export const DidChangeRowsNotificationType = new IpcNotificationType<DidChangeRowsParams>(
'graph/rows/didChange',
undefined,
true,
);
export interface DidChangeRowsStatsParams { export interface DidChangeRowsStatsParams {
rowsStats: Record<string, GraphRowStats>; rowsStats: Record<string, GraphRowStats>;

+ 3
- 1
src/system/logger.scope.ts View File

@ -18,7 +18,9 @@ export function getLogScope(): LogScope | undefined {
return scopes.get(scopeCounter); return scopes.get(scopeCounter);
} }
export function getNewLogScope(prefix: string): LogScope {
export function getNewLogScope(prefix: string, scope?: LogScope | undefined): LogScope {
if (scope != null) return { scopeId: scope.scopeId, prefix: `${scope.prefix}${prefix}` };
const scopeId = getNextLogScopeId(); const scopeId = getNextLogScopeId();
return { return {
scopeId: scopeId, scopeId: scopeId,

+ 2
- 5
src/webviews/apps/commitDetails/commitDetails.ts View File

@ -105,10 +105,7 @@ export class CommitDetailsApp extends App> {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
// case DidChangeRichStateNotificationType.method: // case DidChangeRichStateNotificationType.method:
// onIpc(DidChangeRichStateNotificationType, msg, params => { // onIpc(DidChangeRichStateNotificationType, msg, params => {
@ -152,7 +149,7 @@ export class CommitDetailsApp extends App> {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }

+ 2
- 6
src/webviews/apps/home/home.ts View File

@ -38,13 +38,9 @@ export class HomeApp extends App {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeRepositoriesType.method: case DidChangeRepositoriesType.method:
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
onIpc(DidChangeRepositoriesType, msg, params => { onIpc(DidChangeRepositoriesType, msg, params => {
this.state.repositories = params; this.state.repositories = params;
this.state.timestamp = Date.now(); this.state.timestamp = Date.now();
@ -53,7 +49,7 @@ export class HomeApp extends App {
}); });
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
break; break;
} }
} }

+ 2
- 6
src/webviews/apps/plus/account/account.ts View File

@ -31,13 +31,9 @@ export class AccountApp extends App {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeSubscriptionNotificationType.method: case DidChangeSubscriptionNotificationType.method:
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
onIpc(DidChangeSubscriptionNotificationType, msg, params => { onIpc(DidChangeSubscriptionNotificationType, msg, params => {
this.state.subscription = params.subscription; this.state.subscription = params.subscription;
this.state.avatar = params.avatar; this.state.avatar = params.avatar;
@ -48,7 +44,7 @@ export class AccountApp extends App {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
break; break;
} }
} }

+ 3
- 4
src/webviews/apps/plus/focus/focus.ts View File

@ -118,10 +118,7 @@ export class FocusApp extends App {
} }
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeNotificationType.method: case DidChangeNotificationType.method:
onIpc(DidChangeNotificationType, msg, params => { onIpc(DidChangeNotificationType, msg, params => {
@ -130,6 +127,8 @@ export class FocusApp extends App {
this.attachState(); this.attachState();
}); });
break; break;
default:
super.onMessageReceived?.(msg);
} }
} }
} }

+ 20
- 20
src/webviews/apps/plus/graph/graph.tsx View File

@ -51,7 +51,9 @@ import {
UpdateSelectionCommandType, UpdateSelectionCommandType,
} from '../../../../plus/webviews/graph/protocol'; } from '../../../../plus/webviews/graph/protocol';
import { Color, darken, getCssVariable, lighten, mix, opacity } from '../../../../system/color'; import { Color, darken, getCssVariable, lighten, mix, opacity } from '../../../../system/color';
import { debug } from '../../../../system/decorators/log';
import { debounce } from '../../../../system/function'; import { debounce } from '../../../../system/function';
import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope';
import type { IpcMessage, IpcNotificationType } from '../../../protocol'; import type { IpcMessage, IpcNotificationType } from '../../../protocol';
import { onIpc } from '../../../protocol'; import { onIpc } from '../../../protocol';
import { App } from '../../shared/appBase'; import { App } from '../../shared/appBase';
@ -73,7 +75,7 @@ const graphLaneThemeColors = new Map([
]); ]);
export class GraphApp extends App<State> { export class GraphApp extends App<State> {
private callback?: UpdateStateCallback;
private updateStateCallback?: UpdateStateCallback;
constructor() { constructor() {
super('GraphApp'); super('GraphApp');
@ -93,7 +95,7 @@ export class GraphApp extends App {
<GraphWrapper <GraphWrapper
nonce={this.state.nonce} nonce={this.state.nonce}
state={this.state} state={this.state}
subscriber={(callback: UpdateStateCallback) => this.registerEvents(callback)}
subscriber={(updateState: UpdateStateCallback) => this.registerUpdateStateCallback(updateState)}
onColumnsChange={debounce<GraphApp['onColumnsChanged']>( onColumnsChange={debounce<GraphApp['onColumnsChanged']>(
settings => this.onColumnsChanged(settings), settings => this.onColumnsChanged(settings),
250, 250,
@ -139,14 +141,13 @@ export class GraphApp extends App {
// } // }
// } // }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
protected override onMessageReceived(msg: IpcMessage) {
const scope = getLogScope();
switch (msg.method) { switch (msg.method) {
case DidChangeNotificationType.method: case DidChangeNotificationType.method:
onIpc(DidChangeNotificationType, msg, (params, type) => { onIpc(DidChangeNotificationType, msg, (params, type) => {
this.setState({ ...this.state, ...params.state }, type);
this.setState({ ...this.state, ...params }, type);
}); });
break; break;
@ -215,7 +216,8 @@ export class GraphApp extends App {
const newRowsLength = params.rows.length; const newRowsLength = params.rows.length;
this.log( this.log(
`onMessageReceived(${msg.id}:${msg.method}): paging in ${newRowsLength} rows into existing ${previousRowsLength} rows at ${params.paging.startingCursor} (last existing row: ${lastId})`,
scope,
`paging in ${newRowsLength} rows into existing ${previousRowsLength} rows at ${params.paging.startingCursor} (last existing row: ${lastId})`,
); );
rows = []; rows = [];
@ -223,18 +225,14 @@ export class GraphApp extends App {
rows.length = previousRowsLength + newRowsLength; rows.length = previousRowsLength + newRowsLength;
if (params.paging.startingCursor !== lastId) { if (params.paging.startingCursor !== lastId) {
this.log(
`onMessageReceived(${msg.id}:${msg.method}): searching for ${params.paging.startingCursor} in existing rows`,
);
this.log(scope, `searching for ${params.paging.startingCursor} in existing rows`);
let i = 0; let i = 0;
let row; let row;
for (row of previousRows) { for (row of previousRows) {
rows[i++] = row; rows[i++] = row;
if (row.sha === params.paging.startingCursor) { if (row.sha === params.paging.startingCursor) {
this.log(
`onMessageReceived(${msg.id}:${msg.method}): found ${params.paging.startingCursor} in existing rows`,
);
this.log(scope, `found ${params.paging.startingCursor} in existing rows`);
previousRowsLength = i; previousRowsLength = i;
@ -256,7 +254,7 @@ export class GraphApp extends App {
rows[previousRowsLength + i] = params.rows[i]; rows[previousRowsLength + i] = params.rows[i];
} }
} else { } else {
this.log(`onMessageReceived(${msg.id}:${msg.method}): setting to ${params.rows.length} rows`);
this.log(scope, `setting to ${params.rows.length} rows`);
if (params.rows.length === 0) { if (params.rows.length === 0) {
rows = this.state.rows; rows = this.state.rows;
@ -281,6 +279,8 @@ export class GraphApp extends App {
} }
this.state.loading = false; this.state.loading = false;
this.setState(this.state, type); this.setState(this.state, type);
setLogScopeExit(scope, ` \u2022 rows=${this.state.rows?.length ?? 0}`);
}); });
break; break;
@ -339,7 +339,7 @@ export class GraphApp extends App {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }
@ -474,14 +474,14 @@ export class GraphApp extends App {
this.setState(this.state, 'didChangeTheme'); this.setState(this.state, 'didChangeTheme');
} }
@debug({ args: false, singleLine: true })
protected override setState(state: State, type?: IpcNotificationType<any> | InternalNotificationType) { protected override setState(state: State, type?: IpcNotificationType<any> | InternalNotificationType) {
this.log(`setState()`);
const themingChanged = this.ensureTheming(state); const themingChanged = this.ensureTheming(state);
this.state = state; this.state = state;
super.setState({ timestamp: state.timestamp, selectedRepository: state.selectedRepository }); super.setState({ timestamp: state.timestamp, selectedRepository: state.selectedRepository });
this.callback?.(this.state, type, themingChanged);
this.updateStateCallback?.(this.state, type, themingChanged);
} }
private ensureTheming(state: State): boolean { private ensureTheming(state: State): boolean {
@ -691,11 +691,11 @@ export class GraphApp extends App {
}); });
} }
private registerEvents(callback: UpdateStateCallback): () => void {
this.callback = callback;
private registerUpdateStateCallback(updateState: UpdateStateCallback): () => void {
this.updateStateCallback = updateState;
return () => { return () => {
this.callback = undefined;
this.updateStateCallback = undefined;
}; };
} }
} }

+ 2
- 5
src/webviews/apps/plus/patchDetails/patchDetails.ts View File

@ -135,10 +135,7 @@ export class PatchDetailsApp extends App> {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
// case DidChangeRichStateNotificationType.method: // case DidChangeRichStateNotificationType.method:
// onIpc(DidChangeRichStateNotificationType, msg, params => { // onIpc(DidChangeRichStateNotificationType, msg, params => {
@ -222,7 +219,7 @@ export class PatchDetailsApp extends App> {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }

+ 2
- 6
src/webviews/apps/plus/timeline/timeline.ts View File

@ -48,13 +48,9 @@ export class TimelineApp extends App {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeNotificationType.method: case DidChangeNotificationType.method:
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
onIpc(DidChangeNotificationType, msg, params => { onIpc(DidChangeNotificationType, msg, params => {
this.state = params.state; this.state = params.state;
this.setState(this.state); this.setState(this.state);
@ -63,7 +59,7 @@ export class TimelineApp extends App {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }

+ 3
- 6
src/webviews/apps/rebase/rebase.ts View File

@ -1,6 +1,7 @@
/*global document window*/ /*global document window*/
import './rebase.scss'; import './rebase.scss';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
import type { IpcMessage } from '../../protocol';
import { onIpc } from '../../protocol'; import { onIpc } from '../../protocol';
import type { RebaseEntry, RebaseEntryAction, State } from '../../rebase/protocol'; import type { RebaseEntry, RebaseEntryAction, State } from '../../rebase/protocol';
import { import {
@ -318,13 +319,9 @@ class RebaseEditor extends App {
}); });
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data;
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeNotificationType.method: case DidChangeNotificationType.method:
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
onIpc(DidChangeNotificationType, msg, params => { onIpc(DidChangeNotificationType, msg, params => {
this.state = params.state; this.state = params.state;
this.setState(this.state); this.setState(this.state);
@ -333,7 +330,7 @@ class RebaseEditor extends App {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }

+ 2
- 6
src/webviews/apps/settings/settings.ts View File

@ -133,11 +133,7 @@ export class SettingsApp extends App {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidOpenAnchorNotificationType.method: { case DidOpenAnchorNotificationType.method: {
onIpc(DidOpenAnchorNotificationType, msg, params => { onIpc(DidOpenAnchorNotificationType, msg, params => {
@ -157,7 +153,7 @@ export class SettingsApp extends App {
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
} }
} }

+ 37
- 8
src/webviews/apps/shared/appBase.ts View File

@ -1,7 +1,11 @@
/*global window document*/ /*global window document*/
import type { CustomEditorIds, WebviewIds, WebviewViewIds } from '../../../constants'; import type { CustomEditorIds, WebviewIds, WebviewViewIds } from '../../../constants';
import { debug } from '../../../system/decorators/log';
import { debounce } from '../../../system/function'; import { debounce } from '../../../system/function';
import { Logger } from '../../../system/logger'; import { Logger } from '../../../system/logger';
import type { LogScope } from '../../../system/logger.scope';
import { getLogScope, getNewLogScope } from '../../../system/logger.scope';
import { maybeStopWatch } from '../../../system/stopwatch';
import type { import type {
IpcCommandType, IpcCommandType,
IpcMessage, IpcMessage,
@ -38,6 +42,8 @@ function nextIpcId() {
return `webview:${ipcSequence}`; return `webview:${ipcSequence}`;
} }
const textDecoder = new TextDecoder();
export abstract class App< export abstract class App<
State extends { webviewId: CustomEditorIds | WebviewIds | WebviewViewIds; timestamp: number } = { State extends { webviewId: CustomEditorIds | WebviewIds | WebviewViewIds; timestamp: number } = {
webviewId: CustomEditorIds | WebviewIds | WebviewViewIds; webviewId: CustomEditorIds | WebviewIds | WebviewViewIds;
@ -77,7 +83,7 @@ export abstract class App<
DEBUG ? 'debug' : 'off', DEBUG ? 'debug' : 'off',
); );
this.log(`ctor()`);
this.log(`${appName}()`);
// this.log(`ctor(${this.state ? JSON.stringify(this.state) : ''})`); // this.log(`ctor(${this.state ? JSON.stringify(this.state) : ''})`);
this._api = acquireVsCodeApi(); this._api = acquireVsCodeApi();
@ -93,14 +99,14 @@ export abstract class App<
disposables.push(watchThemeColors()); disposables.push(watchThemeColors());
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.log(`ctor(): initializing...`);
this.log(`${appName}(): initializing...`);
try { try {
this.onInitialize?.(); this.onInitialize?.();
this.bind(); this.bind();
if (this.onMessageReceived != null) { if (this.onMessageReceived != null) {
disposables.push(DOM.on(window, 'message', this.onMessageReceived.bind(this)));
disposables.push(DOM.on(window, 'message', e => this.onMessageReceivedCore(e)));
} }
this.sendCommand(WebviewReadyCommandType, undefined); this.sendCommand(WebviewReadyCommandType, undefined);
@ -127,9 +133,26 @@ export abstract class App<
protected onInitialize?(): void; protected onInitialize?(): void;
protected onBind?(): Disposable[]; protected onBind?(): Disposable[];
protected onInitialized?(): void; protected onInitialized?(): void;
protected onMessageReceived?(e: MessageEvent): void;
protected onMessageReceived?(msg: IpcMessage): void;
protected onThemeUpdated?(e: ThemeChangeEvent): void; protected onThemeUpdated?(e: ThemeChangeEvent): void;
@debug<App['onMessageReceivedCore']>({ args: { 0: e => `${e.data.id}, method=${e.data.method}` } })
private onMessageReceivedCore(e: MessageEvent) {
const scope = getLogScope();
const msg = e.data as IpcMessage;
if (msg.packed && msg.params instanceof Uint8Array) {
const sw = maybeStopWatch(getNewLogScope(` deserializing msg=${e.data.method}`, scope), {
log: false,
logLevel: 'debug',
});
msg.params = JSON.parse(textDecoder.decode(msg.params));
sw?.stop();
}
this.onMessageReceived!(msg);
}
private _focused?: boolean; private _focused?: boolean;
private _inputFocused?: boolean; private _inputFocused?: boolean;
@ -166,8 +189,14 @@ export abstract class App<
); );
} }
protected log(message: string, ...optionalParams: any[]) {
Logger.log(message, ...optionalParams);
protected log(message: string, ...optionalParams: any[]): void;
protected log(scope: LogScope | undefined, message: string, ...optionalParams: any[]): void;
protected log(scopeOrMessage: LogScope | string | undefined, ...optionalParams: any[]): void {
if (typeof scopeOrMessage === 'string') {
Logger.log(scopeOrMessage, ...optionalParams);
} else {
Logger.log(scopeOrMessage, optionalParams.shift(), ...optionalParams);
}
} }
protected getState(): State | undefined { protected getState(): State | undefined {
@ -179,7 +208,7 @@ export abstract class App<
params: IpcMessageParams<TCommand>, params: IpcMessageParams<TCommand>,
): void { ): void {
const id = nextIpcId(); const id = nextIpcId();
this.log(`sendCommand(${id}): name=${command.method}`);
this.log(`${this.appName}.sendCommand(${id}): name=${command.method}`);
this.postMessage({ id: id, method: command.method, params: params }); this.postMessage({ id: id, method: command.method, params: params });
} }
@ -193,7 +222,7 @@ export abstract class App<
completion: TCompletion, completion: TCompletion,
): Promise<IpcMessageParams<TCompletion>> { ): Promise<IpcMessageParams<TCompletion>> {
const id = nextIpcId(); const id = nextIpcId();
this.log(`sendCommandWithCompletion(${id}): name=${command.method}`);
this.log(`${this.appName}.sendCommandWithCompletion(${id}): name=${command.method}`);
const promise = new Promise<IpcMessageParams<TCompletion>>((resolve, reject) => { const promise = new Promise<IpcMessageParams<TCompletion>>((resolve, reject) => {
let timeout: ReturnType<typeof setTimeout> | undefined; let timeout: ReturnType<typeof setTimeout> | undefined;

+ 2
- 6
src/webviews/apps/welcome/welcome.ts View File

@ -41,13 +41,9 @@ export class WelcomeApp extends App {
return disposables; return disposables;
} }
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
protected override onMessageReceived(msg: IpcMessage) {
switch (msg.method) { switch (msg.method) {
case DidChangeNotificationType.method: case DidChangeNotificationType.method:
this.log(`onMessageReceived(${msg.id}): name=${msg.method}`);
onIpc(DidChangeNotificationType, msg, params => { onIpc(DidChangeNotificationType, msg, params => {
this.state = params.state; this.state = params.state;
this.setState(this.state); this.setState(this.state);
@ -55,7 +51,7 @@ export class WelcomeApp extends App {
}); });
break; break;
default: default:
super.onMessageReceived?.(e);
super.onMessageReceived?.(msg);
break; break;
} }
} }

+ 2
- 0
src/webviews/protocol.ts View File

@ -5,6 +5,7 @@ import type { ConfigPath, ConfigPathValue, Path, PathValue } from '../system/con
export interface IpcMessage { export interface IpcMessage {
id: string; id: string;
method: string; method: string;
packed?: boolean;
params?: unknown; params?: unknown;
completionId?: string; completionId?: string;
} }
@ -14,6 +15,7 @@ abstract class IpcMessageType {
constructor( constructor(
public readonly method: string, public readonly method: string,
public readonly reset: boolean = false, public readonly reset: boolean = false,
public readonly pack: boolean = false,
) {} ) {}
} }
export type IpcMessageParams<T> = T extends IpcMessageType<infer P> ? P : never; export type IpcMessageParams<T> = T extends IpcMessageType<infer P> ? P : never;

+ 18
- 3
src/webviews/webviewController.ts View File

@ -9,8 +9,9 @@ import { setContext } from '../system/context';
import { debug, logName } from '../system/decorators/log'; import { debug, logName } from '../system/decorators/log';
import { serialize } from '../system/decorators/serialize'; import { serialize } from '../system/decorators/serialize';
import { Logger } from '../system/logger'; import { Logger } from '../system/logger';
import { getLogScope, setLogScopeExit } from '../system/logger.scope';
import { getLogScope, getNewLogScope, setLogScopeExit } from '../system/logger.scope';
import { isPromise } from '../system/promise'; import { isPromise } from '../system/promise';
import { maybeStopWatch } from '../system/stopwatch';
import type { WebviewContext } from '../system/webview'; import type { WebviewContext } from '../system/webview';
import type { import type {
IpcMessage, IpcMessage,
@ -25,6 +26,7 @@ import type { WebviewPanelDescriptor, WebviewShowOptions, WebviewViewDescriptor
const maxSmallIntegerV8 = 2 ** 30; // Max number that can be stored in V8's smis (small integers) const maxSmallIntegerV8 = 2 ** 30; // Max number that can be stored in V8's smis (small integers)
const utf8TextDecoder = new TextDecoder('utf8'); const utf8TextDecoder = new TextDecoder('utf8');
const utf8TextEncoder = new TextEncoder();
let ipcSequence = 0; let ipcSequence = 0;
function nextIpcId() { function nextIpcId() {
@ -385,7 +387,7 @@ export class WebviewController<
} }
@debug<WebviewController<State>['onMessageReceivedCore']>({ @debug<WebviewController<State>['onMessageReceivedCore']>({
args: { 0: e => (e != null ? `${e.id}: method=${e.method}` : '<undefined>') },
args: { 0: e => (e != null ? `${e.id}, method=${e.method}` : '<undefined>') },
}) })
private onMessageReceivedCore(e: IpcMessage) { private onMessageReceivedCore(e: IpcMessage) {
if (e == null) return; if (e == null) return;
@ -534,10 +536,23 @@ export class WebviewController<
params: IpcMessageParams<T>, params: IpcMessageParams<T>,
completionId?: string, completionId?: string,
): Promise<boolean> { ): Promise<boolean> {
let packed;
if (type.pack && params != null) {
const scope = getLogScope();
const sw = maybeStopWatch(getNewLogScope(` serializing msg=${type.method}`, scope), {
log: false,
logLevel: 'debug',
});
packed = utf8TextEncoder.encode(JSON.stringify(params));
sw?.stop();
}
const msg: IpcMessage = { const msg: IpcMessage = {
id: this.nextIpcId(), id: this.nextIpcId(),
method: type.method, method: type.method,
params: params,
params: packed ?? params,
packed: packed != null,
completionId: completionId, completionId: completionId,
}; };

Loading…
Cancel
Save