Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions .claude/skills/playwright-dev/trace_system_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,20 @@ The Playwright trace system is a comprehensive recording and visualization frame

## 2. File Structure

### packages/trace/src/ - Trace Type Definitions
Located in `/home/pfeldman/code/playwright/packages/trace/src/`
### packages/isomorphic/trace/ - Trace Type Definitions

**Key Files:**
- **trace.ts** - Core trace event type definitions
- **har.ts** - HTTP Archive format (network traffic)
- **snapshot.ts** - DOM snapshot data structures
- **DEPS.list** - Dependencies marker
- **trace.ts** - Current trace event and snapshot types; re-exports the latest version
- **versions/** - One file per trace format version, plus legacy formats kept for modernization
- **versions/har.ts** - HTTP Archive format (network traffic)

**File List:**
```
trace/src/
├── trace.ts (183 lines) - Main trace event types
── har.ts (189 lines) - HAR format types
├── snapshot.ts (62 lines) - Snapshot data structures
└── DEPS.list - Dependencies file
isomorphic/trace/
├── trace.ts - Current trace event + snapshot types (re-export)
── versions/
├── traceV*.ts - Per-version trace event types
└── har.ts - HAR format types
```

---
Expand Down Expand Up @@ -206,7 +204,7 @@ type ErrorTraceEvent = {

---

## 4. HAR Format (har.ts)
## 4. HAR Format (versions/har.ts)

Follows HTTP Archive 1.2 specification. Key structure for network traffic:

Expand Down Expand Up @@ -247,7 +245,7 @@ type Entry = {

---

## 5. Snapshot Format (snapshot.ts)
## 5. Snapshot Format (trace.ts)

### FrameSnapshot
```typescript
Expand Down Expand Up @@ -915,9 +913,8 @@ Every action uses a unique `callId` to correlate:

| File | Size | Purpose |
|------|------|---------|
| `trace/src/trace.ts` | 183 lines | Trace event types |
| `trace/src/har.ts` | 189 lines | Network HAR types |
| `trace/src/snapshot.ts` | 62 lines | Snapshot types |
| `isomorphic/trace/trace.ts` | Trace event and snapshot types |
| `isomorphic/trace/versions/har.ts` | Network HAR types |
| `playwright-core/.../tracing.ts` | 700+ lines | Recording engine |
| `playwright-core/.../traceParser.ts` | 62 lines | ZIP backend |
| `playwright-core/.../traceViewer.ts` | 288 lines | Viewer server |
Expand Down
5 changes: 2 additions & 3 deletions packages/isomorphic/trace/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
*/

import type { Language } from '../locatorGenerators';
import type { ResourceSnapshot } from '@trace/snapshot';
import type * as trace from '@trace/trace';
import type * as trace from './trace';

// *Entry structures are used to pass the trace between the sw and the page.

Expand All @@ -35,7 +34,7 @@ export type ContextEntry = {
title?: string;
options: trace.BrowserContextEventOptions;
pages: PageEntry[];
resources: ResourceSnapshot[];
resources: trace.ResourceSnapshot[];
actions: ActionEntry[];
screenshots: trace.ScreenshotTraceEvent[];
ariaSnapshots: trace.AriaSnapshotTraceEvent[];
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/snapshotRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { escapeHTMLAttribute, escapeHTML } from '../stringUtils';

import type { FrameSnapshot, NodeNameAttributesChildNodesSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot, SubtreeReferenceSnapshot } from '@trace/snapshot';
import type { FrameSnapshot, NodeNameAttributesChildNodesSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot, SubtreeReferenceSnapshot } from './trace';
import type { PageEntry } from './entries';
import type { LRUCache } from '../lruCache';

Expand Down
3 changes: 1 addition & 2 deletions packages/isomorphic/trace/snapshotServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
import type { URLSearchParams } from 'url';
import type { SnapshotRenderer } from './snapshotRenderer';
import type { SnapshotStorage } from './snapshotStorage';
import type { ResourceSnapshot } from '@trace/snapshot';
import type { ActionPhase } from '@trace/trace';
import type { ActionPhase, ResourceSnapshot } from './trace';

export class SnapshotServer {
private _snapshotStorage: SnapshotStorage;
Expand Down
3 changes: 1 addition & 2 deletions packages/isomorphic/trace/snapshotStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
import { rewriteURLForCustomProtocol, SnapshotRenderer } from './snapshotRenderer';
import { LRUCache } from '../lruCache';

import type { FrameSnapshot, ResourceSnapshot } from '@trace/snapshot';
import type { ActionPhase } from '@trace/trace';
import type { ActionPhase, FrameSnapshot, ResourceSnapshot } from './trace';
import type { PageEntry } from './entries';


Expand Down
17 changes: 17 additions & 0 deletions packages/isomorphic/trace/trace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export type * from './versions/traceV9';
11 changes: 7 additions & 4 deletions packages/isomorphic/trace/traceModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
import { getActionGroup, renderFullTitleForCall } from '../protocolFormatter';

import type { Language } from '../locatorGenerators';
import type { ResourceSnapshot } from '@trace/snapshot';
import type * as trace from '@trace/trace';
import type { ActionTraceEvent } from '@trace/trace';
import type * as trace from './trace';
import type { ActionTraceEvent, ResourceSnapshot } from './trace';
import type { ActionEntry, ContextEntry, PageEntry } from './entries';
import type { ActionGroup } from '../protocolFormatter';

Expand Down Expand Up @@ -369,7 +368,11 @@ function adjustMonotonicTime(context: ContextEntry, monotonicTimeDelta: number)
frame.timestamp += monotonicTimeDelta;
}
for (const video of context.videos || [])
video.timestampOrigin += monotonicTimeDelta;
video.timestamp += monotonicTimeDelta;
for (const screenshot of context.screenshots || [])
screenshot.timestamp += monotonicTimeDelta;
for (const ariaSnapshot of context.ariaSnapshots || [])
ariaSnapshot.timestamp += monotonicTimeDelta;
for (const resource of context.resources) {
if (resource._monotonicTime)
resource._monotonicTime += monotonicTimeDelta;
Expand Down
100 changes: 44 additions & 56 deletions packages/isomorphic/trace/traceModernizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
* limitations under the License.
*/

import type * as trace from '@trace/trace';
import type * as trace from './trace';
import type * as traceV3 from './versions/traceV3';
import type * as traceV4 from './versions/traceV4';
import type * as traceV5 from './versions/traceV5';
import type * as traceV6 from './versions/traceV6';
import type * as traceV7 from './versions/traceV7';
import type * as traceV8 from './versions/traceV8';
import type { FrameSnapshot } from '@trace/snapshot';
import type { ActionEntry, ContextEntry, PageEntry } from './entries';
import type { SnapshotStorage } from './snapshotStorage';

Expand All @@ -32,9 +31,6 @@ export class TraceVersionError extends Error {
}
}

// 6 => 10/2023 ~1.40
// 7 => 05/2024 ~1.45
// 9 => 08/2026 ~1.63
const latestVersion: trace.VERSION = 9;

// Ensures distinct api request refs across contexts of the same trace.
Expand Down Expand Up @@ -230,48 +226,9 @@ export class TraceModernizer {
let events = [event];
for (; version < latestVersion; ++version)
events = (this as any)[`_modernize_${version}_to_${version + 1}`].call(this, events);
for (const e of events)
this._normalizeResourceReferences(e);
return events;
}

// Traces recorded before trace-relative paths referenced blobs by bare sha1-style names:
// `_sha1` in har entry content, `sha1` in snapshot resource overrides, screencast frames
// and attachments.
private _normalizeResourceReferences(event: any) {
if (event.type === 'resource-snapshot') {
const { request, response } = event.snapshot;
if (request?.postData?._sha1) {
request.postData._file = 'resources/' + request.postData._sha1;
delete request.postData._sha1;
}
if (response?.content?._sha1) {
response.content._file = 'resources/' + response.content._sha1;
delete response.content._sha1;
}
}
if (event.type === 'frame-snapshot') {
for (const override of event.snapshot.resourceOverrides || []) {
if (override.sha1) {
override.file = 'resources/' + override.sha1;
delete override.sha1;
}
}
}
if (event.type === 'screencast-frame' && event.sha1) {
event.file = 'resources/' + event.sha1;
delete event.sha1;
}
if (event.type === 'after' || event.type === 'action') {
for (const attachment of event.attachments || []) {
if (attachment.sha1) {
attachment.file = 'resources/' + attachment.sha1;
delete attachment.sha1;
}
}
}
}

_modernize_0_to_1(events: any[]): any[] {
for (const event of events) {
if (event.type !== 'action')
Expand Down Expand Up @@ -522,19 +479,50 @@ export class TraceModernizer {
delete action.inputSnapshot;
delete action.afterSnapshot;
}
if (event.type === 'frame-snapshot' && event.snapshot.snapshotName)
(event.snapshot as FrameSnapshot).phase = this._snapshotPhases.get(event.snapshot.snapshotName);

if (event.type !== 'resource-snapshot')
continue;
const snapshot = event.snapshot;
// Older traces marked api requests with a boolean instead of referencing
// their api request context.
if ((snapshot as any)._apiRequest) {
if (!this._apiRequestRef)
this._apiRequestRef = 'api-request-context@' + (++lastApiRequestRefOrdinal);
snapshot._apiRequestRef = this._apiRequestRef;
delete (snapshot as any)._apiRequest;
// Blobs used to be referenced by a bare sha1-style name, now they use a trace-relative path.
if (event.type === 'after' || event.type === 'action') {
for (const attachment of event.attachments || []) {
if (attachment.sha1) {
(attachment as trace.AfterActionTraceEventAttachment).file = 'resources/' + attachment.sha1;
delete attachment.sha1;
}
}
}
if (event.type === 'screencast-frame' && event.sha1) {
(event as any as trace.ScreencastFrameTraceEvent).file = 'resources/' + event.sha1;
delete (event as any).sha1;
}

if (event.type === 'frame-snapshot') {
if (event.snapshot.snapshotName)
(event.snapshot as trace.FrameSnapshot).phase = this._snapshotPhases.get(event.snapshot.snapshotName);
for (const override of event.snapshot.resourceOverrides || []) {
if (override.sha1) {
(override as trace.ResourceOverride).file = 'resources/' + override.sha1;
delete override.sha1;
}
}
}

if (event.type === 'resource-snapshot') {
const postData = event.snapshot.request?.postData;
if (postData?._sha1) {
postData._file = 'resources/' + postData._sha1;
delete postData._sha1;
}
const content = event.snapshot.response?.content;
if (content?._sha1) {
content._file = 'resources/' + content._sha1;
delete content._sha1;
}
// Older hars marked api requests with a boolean instead of referencing their api request context.
if (event.snapshot._apiRequest) {
if (!this._apiRequestRef)
this._apiRequestRef = 'api-request-context@' + (++lastApiRequestRefOrdinal);
(event as trace.ResourceSnapshotTraceEvent).snapshot._apiRequestRef = this._apiRequestRef;
delete event.snapshot._apiRequest;
}
}
}
return events as trace.TraceEvent[];
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/traceUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { StackFrame } from '@trace/trace';
import type { StackFrame } from './trace';
import type { ClientSideCallMetadata } from '@protocol/structs';

export type SerializedStackFrame = [number, number, number, string];
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/versions/traceV3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { Entry as ResourceSnapshot } from '@trace/har';
import type { Entry as ResourceSnapshot } from './har';

type SerializedValue = {
n?: number,
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/versions/traceV4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { Entry as ResourceSnapshot } from '@trace/har';
import type { Entry as ResourceSnapshot } from './har';

type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl';
type Point = { x: number, y: number };
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/versions/traceV5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/


import type { Entry as ResourceSnapshot } from '@trace/har';
import type { Entry as ResourceSnapshot } from './har';

type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl';
type Point = { x: number, y: number };
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/versions/traceV6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { Entry as ResourceSnapshot } from '@trace/har';
import type { Entry as ResourceSnapshot } from './har';

type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl';
type Point = { x: number, y: number };
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/trace/versions/traceV7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { Entry as ResourceSnapshot } from '@trace/har';
import type { Entry as ResourceSnapshot } from './har';

type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl';
type Point = { x: number, y: number };
Expand Down
Loading
Loading