Skip to content
Open
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
30 changes: 20 additions & 10 deletions packages/utils/src/lib/profiler/trace-file-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,32 +335,42 @@ function processDetail<T extends { detail?: unknown }>(
return target;
}

function encodeDetailToString<T extends { detail?: unknown }>(
target: T,
): T & { detail?: string } {
return processDetail(target, (detail: string | object) =>
typeof detail === 'object' ? JSON.stringify(detail) : detail,
) as T & { detail?: string };
}

/**
* Decodes a JSON string detail property back to its original object form.
* @param target - Object containing a detail property as a JSON string
* @returns UserTimingDetail with the detail property parsed from JSON
*/
export function decodeDetail(target: { detail: string }): UserTimingDetail {
export function decodeDetail<T extends { detail?: string | object }>(
target: T,
): T {
return processDetail(target, detail =>
typeof detail === 'string'
? (JSON.parse(detail) as string | object)
: detail,
) as UserTimingDetail;
);
}

/**
* Encodes object detail properties to JSON strings for storage/transmission.
* @param target - UserTimingDetail object with detail property to encode
* @returns UserTimingDetail with object details converted to JSON strings
*/
export function encodeDetail(target: UserTimingDetail): UserTimingDetail {
export function encodeDetail<T extends { detail?: string | object }>(
target: T,
): T {
return processDetail(
target as UserTimingDetail & { detail?: unknown },
target as T & { detail?: unknown },
(detail: string | object) =>
typeof detail === 'object'
? JSON.stringify(detail as UserTimingDetail)
: detail,
) as UserTimingDetail;
typeof detail === 'object' ? JSON.stringify(detail) : detail,
);
}

/**
Expand Down Expand Up @@ -406,13 +416,13 @@ export function encodeTraceEvent({
return rest as TraceEventRaw;
}

const processedArgs = encodeDetail(args as UserTimingDetail);
const processedArgs = encodeDetailToString(args as { detail?: unknown });
if ('data' in args && args.data && typeof args.data === 'object') {
const result: TraceEventRaw = {
...rest,
args: {
...processedArgs,
data: encodeDetail(args.data as UserTimingDetail),
data: encodeDetailToString(args.data as { detail?: unknown }),
},
};
return result;
Expand Down
62 changes: 45 additions & 17 deletions packages/utils/src/lib/profiler/trace-file-utils.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,16 +623,18 @@ describe('getTraceMetadata', () => {

describe('decodeDetail', () => {
it('should decode string detail back to object', () => {
const input = { detail: '{"key": "value"}' };
const input = {
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
};
const result = decodeDetail(input);

expect(result).toStrictEqual({
detail: { key: 'value' },
detail: { devtools: { dataType: 'marker', color: 'primary' } },
});
});

it('should return object detail unchanged', () => {
const input = { detail: { key: 'value' } };
const input = { detail: { devtools: { dataType: 'marker' as const } } };
const result = decodeDetail(input);

expect(result).toStrictEqual(input);
Expand All @@ -655,11 +657,11 @@ describe('decodeDetail', () => {

describe('encodeDetail', () => {
it('should encode object detail to JSON string', () => {
const input = { detail: { key: 'value' } };
const input = { detail: { devtools: { dataType: 'marker' as const } } };
const result = encodeDetail(input);

expect(result).toStrictEqual({
detail: '{"key":"value"}',
detail: '{"devtools":{"dataType":"marker"}}',
});
});

Expand Down Expand Up @@ -695,8 +697,11 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom": "data"}',
data: { detail: '{"nested": "value"}' },
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
data: {
detail:
'{"devtools":{"dataType":"track-entry","track":"test-track"}}',
},
},
};

Expand All @@ -710,8 +715,14 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
data: { detail: { nested: 'value' } },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
data: {
detail: {
devtools: { dataType: 'track-entry' as const, track: 'test-track' },
},
},
},
});
});
Expand All @@ -724,6 +735,7 @@ describe('decodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
};

const result = decodeTraceEvent(rawEvent);
Expand All @@ -735,6 +747,7 @@ describe('decodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
});
});

Expand All @@ -747,7 +760,7 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom": "data"}',
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
},
};

Expand All @@ -761,7 +774,9 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
},
});
});
Expand All @@ -777,8 +792,14 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
data: { detail: { nested: 'value' } },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
data: {
detail: {
devtools: { dataType: 'track-entry' as const, track: 'test-track' },
},
},
},
};

Expand All @@ -792,8 +813,11 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom":"data"}',
data: { detail: '{"nested":"value"}' },
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
data: {
detail:
'{"devtools":{"dataType":"track-entry","track":"test-track"}}',
},
},
});
});
Expand All @@ -806,6 +830,7 @@ describe('encodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
};

const result = encodeTraceEvent(event);
Expand All @@ -817,6 +842,7 @@ describe('encodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
});
});

Expand All @@ -829,7 +855,9 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
},
};

Expand All @@ -843,7 +871,7 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom":"data"}',
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
},
});
});
Expand Down
3 changes: 3 additions & 0 deletions packages/utils/src/lib/reports/load-report.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: 'json',
skipReports: false,
}),
).resolves.toEqual(reportMock());
});
Expand All @@ -38,6 +39,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
format: 'md',
filename: 'report',
skipReports: false,
}),
).resolves.toBe('test-42');
});
Expand All @@ -58,6 +60,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: 'json',
skipReports: false,
}),
).rejects.toThrow('slug has to follow the pattern');
});
Expand Down
6 changes: 6 additions & 0 deletions packages/utils/src/lib/user-timing-extensibility-api.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ export type WithDevToolsPayload<T extends TrackEntryPayload | MarkerPayload> = {
devtools?: T;
};

/**
* Combined detail payload type for performance entries with DevTools support.
*/
export type DetailPayloadWithDevtools = WithDevToolsPayload<
TrackEntryPayload | MarkerPayload
>;
/**
* Extended MarkOptions that supports DevTools payload in detail.
* @example
Expand Down
Loading
Loading