diff --git a/src/client/channelOwner.ts b/src/client/channelOwner.ts index 6a575687de..cf4ea87de7 100644 --- a/src/client/channelOwner.ts +++ b/src/client/channelOwner.ts @@ -103,8 +103,8 @@ export abstract class ChannelOwner {}); + _waitForEventInfoBefore(waitId: string, apiName: string, stack: StackFrame[]) { + this._connection.sendMessageToServer(this._guid, 'waitForEventInfo', { info: { apiName, waitId, phase: 'before', stack } }, undefined).catch(() => {}); } _waitForEventInfoAfter(waitId: string, error?: string) { diff --git a/src/client/waiter.ts b/src/client/waiter.ts index b5f43d9120..5ba59cfa08 100644 --- a/src/client/waiter.ts +++ b/src/client/waiter.ts @@ -29,10 +29,10 @@ export class Waiter { private _waitId: string; private _error: string | undefined; - constructor(channelOwner: ChannelOwner, name: string) { + constructor(channelOwner: ChannelOwner, apiName: string) { this._waitId = createGuid(); this._channelOwner = channelOwner; - this._channelOwner._waitForEventInfoBefore(this._waitId, name, captureStackTrace().frames); + this._channelOwner._waitForEventInfoBefore(this._waitId, apiName, captureStackTrace().frames); this._dispose = [ () => this._channelOwner._waitForEventInfoAfter(this._waitId, this._error) ]; diff --git a/src/dispatchers/dispatcher.ts b/src/dispatchers/dispatcher.ts index 7185f31430..b80b70785d 100644 --- a/src/dispatchers/dispatcher.ts +++ b/src/dispatchers/dispatcher.ts @@ -132,6 +132,7 @@ export class DispatcherConnection { onmessage = (message: object) => {}; private _validateParams: (type: string, method: string, params: any) => any; private _validateMetadata: (metadata: any) => { stack?: StackFrame[] }; + private _waitOperations = new Map(); sendMessageToClient(guid: string, method: string, params: any) { this.onmessage({ guid, method, params: this._replaceDispatchersWithGuids(params) }); @@ -197,7 +198,7 @@ export class DispatcherConnection { } const sdkObject = dispatcher._object instanceof SdkObject ? dispatcher._object : undefined; - const callMetadata: CallMetadata = { + let callMetadata: CallMetadata = { id, ...validMetadata, pageId: sdkObject?.attribution.page?.uniqueId, @@ -211,8 +212,27 @@ export class DispatcherConnection { }; try { - if (sdkObject) + if (sdkObject) { + // Process logs for waitForNavigation/waitForLoadState + if (params?.info?.waitId) { + const info = params.info; + switch (info.phase) { + case 'before': + callMetadata.apiName = info.apiName; + callMetadata.stack = info.stack; + this._waitOperations.set(info.waitId, callMetadata); + break; + case 'log': + const originalMetadata = this._waitOperations.get(info.waitId)!; + originalMetadata.log.push(info.message); + sdkObject.instrumentation.onCallLog('api', info.message, sdkObject, originalMetadata); + // Fall through. + case 'after': + return; + } + } await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata); + } const result = await (dispatcher as any)[method](validParams, callMetadata); this.onmessage({ id, result: this._replaceDispatchersWithGuids(result) }); } catch (e) { @@ -223,8 +243,27 @@ export class DispatcherConnection { this.onmessage({ id, error: serializeError(e) }); } finally { callMetadata.endTime = monotonicTime(); - if (sdkObject) + if (sdkObject) { + // Process logs for waitForNavigation/waitForLoadState + if (params?.info?.waitId) { + const info = params.info; + switch (info.phase) { + case 'before': + callMetadata.endTime = 0; + // Fall through. + case 'log': + return; + case 'after': + const originalMetadata = this._waitOperations.get(info.waitId)!; + originalMetadata.endTime = callMetadata.endTime; + originalMetadata.error = info.error; + this._waitOperations.delete(info.waitId); + callMetadata = originalMetadata; + break; + } + } await sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata); + } } } diff --git a/src/protocol/channels.ts b/src/protocol/channels.ts index 3dc64c6eb4..1f1932424c 100644 --- a/src/protocol/channels.ts +++ b/src/protocol/channels.ts @@ -38,7 +38,7 @@ export type Metadata = { export type WaitForEventInfo = { waitId: string, phase: 'before' | 'after' | 'log', - name?: string, + apiName?: string, stack?: StackFrame[], message?: string, error?: string, diff --git a/src/protocol/protocol.yml b/src/protocol/protocol.yml index f481853776..4beb3a4c76 100644 --- a/src/protocol/protocol.yml +++ b/src/protocol/protocol.yml @@ -41,7 +41,7 @@ WaitForEventInfo: - before - after - log - name: string? + apiName: string? stack: type: array? items: StackFrame diff --git a/src/protocol/validator.ts b/src/protocol/validator.ts index b3193c11c9..4a47567f73 100644 --- a/src/protocol/validator.ts +++ b/src/protocol/validator.ts @@ -46,7 +46,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { scheme.WaitForEventInfo = tObject({ waitId: tString, phase: tEnum(['before', 'after', 'log']), - name: tOptional(tString), + apiName: tOptional(tString), stack: tOptional(tArray(tType('StackFrame'))), message: tOptional(tString), error: tOptional(tString), diff --git a/src/server/supplements/inspectorController.ts b/src/server/supplements/inspectorController.ts index 1bea4896d8..e62a84b2a3 100644 --- a/src/server/supplements/inspectorController.ts +++ b/src/server/supplements/inspectorController.ts @@ -21,8 +21,6 @@ import { CallMetadata, InstrumentationListener, SdkObject } from '../instrumenta import { isDebugMode, isUnderTest } from '../../utils/utils'; export class InspectorController implements InstrumentationListener { - private _waitOperations = new Map(); - async onContextCreated(context: BrowserContext): Promise { if (isDebugMode()) await RecorderSupplement.getOrCreate(context, { pauseOnNextStatement: true }); @@ -33,25 +31,6 @@ export class InspectorController implements InstrumentationListener { if (!context) return; - // Process logs for waitForNavigation/waitForLoadState - if (metadata.params?.info?.waitId) { - const info = metadata.params.info; - switch (info.phase) { - case 'before': - metadata.method = info.name; - metadata.stack = info.stack; - this._waitOperations.set(info.waitId, metadata); - break; - case 'log': - const originalMetadata = this._waitOperations.get(info.waitId)!; - originalMetadata.log.push(info.message); - this.onCallLog('api', info.message, sdkObject, originalMetadata); - // Fall through. - case 'after': - return; - } - } - if (shouldOpenInspector(sdkObject, metadata)) await RecorderSupplement.getOrCreate(context, { pauseOnNextStatement: true }); @@ -62,26 +41,6 @@ export class InspectorController implements InstrumentationListener { async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata): Promise { if (!sdkObject.attribution.context) return; - - // Process logs for waitForNavigation/waitForLoadState - if (metadata.params?.info?.waitId) { - const info = metadata.params.info; - switch (info.phase) { - case 'before': - metadata.endTime = 0; - // Fall through. - case 'log': - return; - case 'after': - const originalMetadata = this._waitOperations.get(info.waitId)!; - originalMetadata.endTime = metadata.endTime; - originalMetadata.error = info.error; - this._waitOperations.delete(info.waitId); - metadata = originalMetadata; - break; - } - } - const recorder = await RecorderSupplement.getNoCreate(sdkObject.attribution.context); await recorder?.onAfterCall(sdkObject, metadata); } @@ -98,7 +57,7 @@ export class InspectorController implements InstrumentationListener { if (!sdkObject.attribution.context) return; const recorder = await RecorderSupplement.getNoCreate(sdkObject.attribution.context); - await recorder?.updateCallLog([metadata]); + recorder?.updateCallLog([metadata]); } } diff --git a/src/server/trace/viewer/traceModel.ts b/src/server/trace/viewer/traceModel.ts index 012b404c8b..305b0c8f29 100644 --- a/src/server/trace/viewer/traceModel.ts +++ b/src/server/trace/viewer/traceModel.ts @@ -83,8 +83,6 @@ export class TraceModel { } case 'action': { const metadata = event.metadata; - if (metadata.method === 'waitForEventInfo') - break; const { pageEntry } = this.pageEntries.get(metadata.pageId!)!; const actionId = event.contextId + '/' + metadata.pageId + '/' + pageEntry.actions.length; const action: ActionEntry = { diff --git a/src/web/traceViewer/ui/actionList.tsx b/src/web/traceViewer/ui/actionList.tsx index e6c28bf39e..9d0921be50 100644 --- a/src/web/traceViewer/ui/actionList.tsx +++ b/src/web/traceViewer/ui/actionList.tsx @@ -43,7 +43,7 @@ export const ActionList: React.FC = ({ onMouseLeave={() => (highlightedAction === actionEntry) && onHighlighted(undefined)} > ; diff --git a/src/web/traceViewer/ui/filmStrip.tsx b/src/web/traceViewer/ui/filmStrip.tsx index 6fa79d013e..523539f4d6 100644 --- a/src/web/traceViewer/ui/filmStrip.tsx +++ b/src/web/traceViewer/ui/filmStrip.tsx @@ -47,12 +47,12 @@ export const FilmStrip: React.FunctionComponent<{ } {previewImage && previewX !== undefined &&
- +
} ; diff --git a/src/web/traceViewer/ui/timeline.css b/src/web/traceViewer/ui/timeline.css index 53e21eaef9..41cca83897 100644 --- a/src/web/traceViewer/ui/timeline.css +++ b/src/web/traceViewer/ui/timeline.css @@ -46,7 +46,7 @@ pointer-events: none; overflow: hidden; flex: none; - flex-basis: 20px; + flex-basis: 30px; position: relative; } @@ -66,10 +66,11 @@ .timeline-bar { position: absolute; - top: 0; - bottom: 0; + height: 9px; + top: 11px; background-color: red; - border-radius: 3px; + border-radius: 2px; + min-width: 3px; --action-color: 'transparent'; background-color: var(--action-color); } @@ -104,16 +105,24 @@ --action-color: var(--blue); } +.timeline-bar.evaluateExpression { + --action-color: var(--yellow); +} + .timeline-bar.dialog { + top: 22px; --action-color: var(--transparent-blue); } .timeline-bar.navigation { - --action-color: var(--purple); + top: 22px; + --action-color: var(--blue); } -.timeline-bar.load { - --action-color: var(--yellow); +.timeline-bar.waitForEventInfo { + bottom: inherit; + top: 0; + --action-color: var(--gray); } .timeline-label { diff --git a/src/web/traceViewer/ui/timeline.tsx b/src/web/traceViewer/ui/timeline.tsx index f57437c694..c861b9a49e 100644 --- a/src/web/traceViewer/ui/timeline.tsx +++ b/src/web/traceViewer/ui/timeline.tsx @@ -65,7 +65,7 @@ export const Timeline: React.FunctionComponent<{ rightTime: entry.metadata.endTime, leftPosition: timeToPosition(measure.width, boundaries, entry.metadata.startTime), rightPosition: timeToPosition(measure.width, boundaries, entry.metadata.endTime), - label: entry.metadata.method + ' ' + detail, + label: entry.metadata.apiName + ' ' + detail, type: entry.metadata.method, priority: 0, });