From cfb2420526b125ec710ea6867449f24a6245920b Mon Sep 17 00:00:00 2001 From: Jason Laster Date: Tue, 24 Sep 2024 11:33:24 -0700 Subject: [PATCH] update replayclient --- packages/shared/client/ReplayClient.ts | 150 ++++++------------------- 1 file changed, 34 insertions(+), 116 deletions(-) diff --git a/packages/shared/client/ReplayClient.ts b/packages/shared/client/ReplayClient.ts index 9f21b931b21..f2300f4a4ce 100644 --- a/packages/shared/client/ReplayClient.ts +++ b/packages/shared/client/ReplayClient.ts @@ -77,21 +77,8 @@ import throttle from "lodash/throttle"; import uniqueId from "lodash/uniqueId"; // eslint-disable-next-line no-restricted-imports -import { - addEventListener, - client, - initSocket, - removeEventListener, - sendMessage, -} from "protocol/socket"; -import { - assert, - breakdownSupplementalId, - compareExecutionPoints, - defer, - transformSupplementalId, - waitForTime, -} from "protocol/utils"; +import { addEventListener, client, initSocket, sendMessage, removeEventListener } from "protocol/socket"; +import { assert, compareExecutionPoints, defer, waitForTime, transformSupplementalId, breakdownSupplementalId } from "protocol/utils"; import { initProtocolMessagesStore } from "replay-next/components/protocol/ProtocolMessagesStore"; import { insert } from "replay-next/src/utils/array"; import { TOO_MANY_POINTS_TO_FIND } from "shared/constants"; @@ -152,11 +139,7 @@ export class ReplayClient implements ReplayClientInterface { // Configures the client to use an already initialized session iD. // This method should be used for apps that use the protocol package directly. // Apps that only communicate with the Replay protocol through this client should use the initialize method instead. - async configure( - recordingId: string, - sessionId: string, - supplemental: SupplementalSession[] - ): Promise { + async configure(recordingId: string, sessionId: string, supplemental: SupplementalSession[]): Promise { this._recordingId = recordingId; this._sessionId = sessionId; this._dispatchEvent("sessionCreated"); @@ -182,9 +165,7 @@ export class ReplayClient implements ReplayClientInterface { return this.supplemental.length; } - private async forEachSession( - callback: (sessionId: string, supplementalIndex: number) => Promise - ) { + private async forEachSession(callback: (sessionId: string, supplementalIndex: number) => Promise) { const sessionId = await this.waitForSession(); await callback(sessionId, 0); for (let i = 0; i < this.supplemental.length; i++) { @@ -201,9 +182,7 @@ export class ReplayClient implements ReplayClientInterface { return supplementalInfo.sessionId; } - private async breakdownSupplementalIdAndSession( - transformedId: string - ): Promise<{ id: string; sessionId: string; supplementalIndex: number }> { + private async breakdownSupplementalIdAndSession(transformedId: string): Promise<{ id: string, sessionId: string, supplementalIndex: number }> { const { id, supplementalIndex } = breakdownSupplementalId(transformedId); const sessionId = await this.getSupplementalIndexSession(supplementalIndex); return { id, sessionId, supplementalIndex }; @@ -211,7 +190,7 @@ export class ReplayClient implements ReplayClientInterface { private async getPauseSessionId(pauseId: string): Promise { const sessionId = this.pauseIdToSessionId.get(pauseId); - return sessionId || (await this.waitForSession()); + return sessionId || await this.waitForSession(); } private getSessionIdSupplementalIndex(sessionId: string) { @@ -243,9 +222,7 @@ export class ReplayClient implements ReplayClientInterface { } async createPause(transformedExecutionPoint: ExecutionPoint): Promise { - const { id: executionPoint, sessionId } = await this.breakdownSupplementalIdAndSession( - transformedExecutionPoint - ); + const { id: executionPoint, sessionId } = await this.breakdownSupplementalIdAndSession(transformedExecutionPoint); await this.waitForPointToBeInFocusRange(executionPoint); @@ -600,13 +577,11 @@ export class ReplayClient implements ReplayClientInterface { transformedPointSelector: PointSelector, pointLimits?: PointPageLimits ): Promise { - const { pointSelector, sessionId } = await this.breakdownSupplementalPointSelector( - transformedPointSelector - ); + const { pointSelector, sessionId } = await this.breakdownSupplementalPointSelector(transformedPointSelector); const points: PointDescription[] = []; const findPointsId = String(this.nextFindPointsId++); - pointLimits = pointLimits && this.isMainSession(sessionId) ? { ...pointLimits } : {}; + pointLimits = (pointLimits && this.isMainSession(sessionId)) ? { ...pointLimits } : {}; if (!pointLimits.maxCount) { pointLimits.maxCount = MAX_POINTS_TO_FIND; } @@ -652,13 +627,7 @@ export class ReplayClient implements ReplayClientInterface { return this.supplemental[supplementalIndex - 1].serverRecordingId; } - private forAllConnections( - callback: ( - serverRecordingId: string, - connection: SupplementalRecordingConnection, - supplementalIndex: number - ) => void - ) { + private forAllConnections(callback: (serverRecordingId: string, connection: SupplementalRecordingConnection, supplementalIndex: number) => void) { this.supplemental.forEach(({ serverRecordingId, connections }, i) => { for (const connection of connections) { callback(serverRecordingId, connection, i + 1); @@ -666,7 +635,9 @@ export class ReplayClient implements ReplayClientInterface { }); } - getTargetPoint(point: ExecutionPoint, pointSupplementalIndex: number): TargetPoint | null { + getTargetPoint(point: ExecutionPoint, pointSupplementalIndex: number): { + point: TimeStampedPoint, supplementalIndex: number + } | null { const recordingId = this.getSupplementalIndexRecordingId(pointSupplementalIndex); let targetPoint: TimeStampedPoint | undefined; @@ -694,10 +665,8 @@ export class ReplayClient implements ReplayClientInterface { return { point: targetPoint, supplementalIndex: targetSupplementalIndex }; } - private async maybeGetConnectionStepTarget( - point: ExecutionPoint, - pointSupplementalIndex: number - ): Promise { + private async maybeGetConnectionStepTarget(point: ExecutionPoint, pointSupplementalIndex: number): Promise { + const targetPoint = this.getTargetPoint(point, pointSupplementalIndex); if (!targetPoint) { return null; @@ -705,11 +674,7 @@ export class ReplayClient implements ReplayClientInterface { const sessionId = await this.getSupplementalIndexSession(targetPoint.supplementalIndex); - const response = await sendMessage( - "Session.getPointFrameSteps" as any, - { point: targetPoint.point }, - sessionId - ); + const response = await sendMessage("Session.getPointFrameSteps" as any, { point: targetPoint.point }, sessionId); const { steps } = response; const desc = steps.find((step: PointDescription) => step.point == targetPoint.point?.point); assert(desc); @@ -719,11 +684,7 @@ export class ReplayClient implements ReplayClientInterface { } async findStepInTarget(transformedPoint: ExecutionPoint): Promise { - const { - id: point, - sessionId, - supplementalIndex, - } = await this.breakdownSupplementalIdAndSession(transformedPoint); + const { id: point, sessionId, supplementalIndex } = await this.breakdownSupplementalIdAndSession(transformedPoint); const connectionStepTarget = await this.maybeGetConnectionStepTarget(point, supplementalIndex); if (connectionStepTarget) { return connectionStepTarget; @@ -765,9 +726,7 @@ export class ReplayClient implements ReplayClientInterface { for (const source of sourcesList) { if (supplementalIndex) { source.sourceId = transformSupplementalId(source.sourceId, supplementalIndex); - source.generatedSourceIds = source.generatedSourceIds?.map(id => - transformSupplementalId(id, supplementalIndex) - ); + source.generatedSourceIds = source.generatedSourceIds?.map(id => transformSupplementalId(id, supplementalIndex)); } sources.push(source); } @@ -787,10 +746,7 @@ export class ReplayClient implements ReplayClientInterface { location.sourceId = transformSupplementalId(location.sourceId, supplementalIndex); } - private transformSupplementalMappedLocation( - mappedLocation: MappedLocation | undefined, - supplementalIndex: number - ) { + private transformSupplementalMappedLocation(mappedLocation: MappedLocation | undefined, supplementalIndex: number) { for (const location of mappedLocation || []) { this.transformSupplementalLocation(location, supplementalIndex); } @@ -843,10 +799,7 @@ export class ReplayClient implements ReplayClientInterface { return result; } - async getPointStack( - transformedPoint: ExecutionPoint, - maxCount: number - ): Promise { + async getPointStack(transformedPoint: ExecutionPoint, maxCount: number): Promise { const { id: point, sessionId } = await this.breakdownSupplementalIdAndSession(transformedPoint); const result = await client.Session.getPointStack({ point, maxCount }, sessionId); return result.frames; @@ -1096,10 +1049,7 @@ export class ReplayClient implements ReplayClientInterface { return screen; } - async mapExpressionToGeneratedScope( - expression: string, - transformedLocation: Location - ): Promise { + async mapExpressionToGeneratedScope(expression: string, transformedLocation: Location): Promise { const { location, sessionId } = await this.breakdownSupplementalLocation(transformedLocation); const result = await client.Debugger.mapExpressionToGeneratedScope( { expression, location }, @@ -1121,27 +1071,18 @@ export class ReplayClient implements ReplayClientInterface { locations: SameLineSourceLocations[], focusRange: PointRange | null ) { - const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession( - transformedSourceId - ); + const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession(transformedSourceId); await this.waitForRangeToBeInFocusRange(focusRange); const { hits } = await client.Debugger.getHitCounts( - { - sourceId, - locations, - maxHits: TOO_MANY_POINTS_TO_FIND, - range: (this.isMainSession(sessionId) && focusRange) || undefined, - }, + { sourceId, locations, maxHits: TOO_MANY_POINTS_TO_FIND, range: (this.isMainSession(sessionId) && focusRange) || undefined }, sessionId ); return hits; } async getSourceOutline(transformedSourceId: SourceId) { - const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession( - transformedSourceId - ); + const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession(transformedSourceId); return client.Debugger.getSourceOutline({ sourceId }, sessionId); } @@ -1149,9 +1090,7 @@ export class ReplayClient implements ReplayClientInterface { transformedSourceId: SourceId, locationRange: SourceLocationRange | null ): Promise { - const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession( - transformedSourceId - ); + const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession(transformedSourceId); const begin = locationRange ? locationRange.start : undefined; const end = locationRange ? locationRange.end : undefined; @@ -1351,11 +1290,9 @@ export class ReplayClient implements ReplayClientInterface { }, onResults: (results: RunEvaluationResult[]) => void ): Promise { - const { pointSelector, sessionId, supplementalIndex } = - await this.breakdownSupplementalPointSelector(opts.selector); + const { pointSelector, sessionId, supplementalIndex } = await this.breakdownSupplementalPointSelector(opts.selector); const runEvaluationId = String(this.nextRunEvaluationId++); - const pointLimits: PointPageLimits = - opts.limits && !supplementalIndex ? { ...opts.limits } : {}; + const pointLimits: PointPageLimits = (opts.limits && !supplementalIndex) ? { ...opts.limits } : {}; if (!pointLimits.maxCount) { pointLimits.maxCount = MAX_POINTS_TO_RUN_EVALUATION; } @@ -1407,9 +1344,7 @@ export class ReplayClient implements ReplayClientInterface { onSourceContentsInfo: (params: sourceContentsInfo) => void, onSourceContentsChunk: (params: sourceContentsChunk) => void ): Promise { - const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession( - transformedSourceId - ); + const { id: sourceId, sessionId } = await this.breakdownSupplementalIdAndSession(transformedSourceId); let pendingChunk = ""; let pendingThrottlePromise: Promise | null = null; @@ -1571,10 +1506,7 @@ function waitForOpenConnection( // // If there is no such delta then we're seeing inconsistent timing information with // the connections and will fall back onto interpolateSupplementalTime. -function computeSupplementalTimeDelta( - recordingId: string, - supplemental: SupplementalSession -): number | undefined { +function computeSupplementalTimeDelta(recordingId: string, supplemental: SupplementalSession): number | undefined { // Delta which ensures that all clientFirst connections happen // on the client before they happen on the server. let clientFirstDelta: number | undefined; @@ -1583,12 +1515,7 @@ function computeSupplementalTimeDelta( // on the server before they happen on the client. let clientLastDelta: number | undefined; - for (const { - clientFirst, - clientRecordingId, - clientPoint, - serverPoint, - } of supplemental.connections) { + for (const { clientFirst, clientRecordingId, clientPoint, serverPoint } of supplemental.connections) { assert(recordingId == clientRecordingId); const delta = serverPoint.time - clientPoint.time; if (clientFirst) { @@ -1617,10 +1544,7 @@ function computeSupplementalTimeDelta( // client events in the connection actually happen before the server // event on the timeline instead of at the exact same time, which can // cause console messages to be rendered in the wrong order. -function adjustInterpolateSupplementalTime( - connection: SupplementalRecordingConnection, - clientTime: number -) { +function adjustInterpolateSupplementalTime(connection: SupplementalRecordingConnection, clientTime: number) { const { clientFirst, clientPoint } = connection; const Epsilon = 0.1; if (clientFirst) { @@ -1641,11 +1565,7 @@ function adjustInterpolateSupplementalTime( // This works even if there is no single consistent delta to use throughout the // recording, and requires that events on either side of the connections happen // in the same order in the two recordings. -function interpolateSupplementalTime( - recordingId: string, - supplemental: SupplementalSession, - supplementalTime: number -): number { +function interpolateSupplementalTime(recordingId: string, supplemental: SupplementalSession, supplementalTime: number): number { assert(supplemental.connections.length); for (const connection of supplemental.connections) { assert(connection.clientRecordingId == recordingId); @@ -1657,10 +1577,8 @@ function interpolateSupplementalTime( const next = supplemental.connections[i]; assert(previous.clientPoint.time <= next.clientPoint.time); assert(previous.serverPoint.time <= next.serverPoint.time); - if ( - supplementalTime >= previous.serverPoint.time && - supplementalTime <= next.serverPoint.time - ) { + if (supplementalTime >= previous.serverPoint.time && + supplementalTime <= next.serverPoint.time) { const clientElapsed = next.clientPoint.time - previous.clientPoint.time; const serverElapsed = next.serverPoint.time - previous.serverPoint.time; const fraction = (supplementalTime - previous.serverPoint.time) / serverElapsed;