perfgraph 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/causal/builder.d.ts +34 -0
- package/dist/causal/builder.d.ts.map +1 -0
- package/dist/causal/builder.js +132 -0
- package/dist/causal/builder.js.map +1 -0
- package/dist/causal/index.d.ts +11 -0
- package/dist/causal/index.d.ts.map +1 -0
- package/dist/causal/index.js +10 -0
- package/dist/causal/index.js.map +1 -0
- package/dist/causal/rules/js.d.ts +49 -0
- package/dist/causal/rules/js.d.ts.map +1 -0
- package/dist/causal/rules/js.js +209 -0
- package/dist/causal/rules/js.js.map +1 -0
- package/dist/causal/rules/layout.d.ts +39 -0
- package/dist/causal/rules/layout.d.ts.map +1 -0
- package/dist/causal/rules/layout.js +169 -0
- package/dist/causal/rules/layout.js.map +1 -0
- package/dist/causal/rules/lcp.d.ts +49 -0
- package/dist/causal/rules/lcp.d.ts.map +1 -0
- package/dist/causal/rules/lcp.js +250 -0
- package/dist/causal/rules/lcp.js.map +1 -0
- package/dist/causal/rules/network.d.ts +39 -0
- package/dist/causal/rules/network.d.ts.map +1 -0
- package/dist/causal/rules/network.js +140 -0
- package/dist/causal/rules/network.js.map +1 -0
- package/dist/causal/types.d.ts +142 -0
- package/dist/causal/types.d.ts.map +1 -0
- package/dist/causal/types.js +88 -0
- package/dist/causal/types.js.map +1 -0
- package/dist/cli/analyze.d.ts +33 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +137 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/collect.d.ts +28 -0
- package/dist/cli/collect.d.ts.map +1 -0
- package/dist/cli/collect.js +125 -0
- package/dist/cli/collect.js.map +1 -0
- package/dist/cli/extract.d.ts +31 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +135 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +53 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/normalize.d.ts +58 -0
- package/dist/cli/normalize.d.ts.map +1 -0
- package/dist/cli/normalize.js +179 -0
- package/dist/cli/normalize.js.map +1 -0
- package/dist/cli/report.d.ts +33 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +137 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/run.d.ts +49 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +243 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/collect/buffer-monitor.d.ts +25 -0
- package/dist/collect/buffer-monitor.d.ts.map +1 -0
- package/dist/collect/buffer-monitor.js +69 -0
- package/dist/collect/buffer-monitor.js.map +1 -0
- package/dist/collect/console.d.ts +25 -0
- package/dist/collect/console.d.ts.map +1 -0
- package/dist/collect/console.js +82 -0
- package/dist/collect/console.js.map +1 -0
- package/dist/collect/coverage.d.ts +26 -0
- package/dist/collect/coverage.d.ts.map +1 -0
- package/dist/collect/coverage.js +99 -0
- package/dist/collect/coverage.js.map +1 -0
- package/dist/collect/dom.d.ts +37 -0
- package/dist/collect/dom.d.ts.map +1 -0
- package/dist/collect/dom.js +118 -0
- package/dist/collect/dom.js.map +1 -0
- package/dist/collect/lighthouse.d.ts +41 -0
- package/dist/collect/lighthouse.d.ts.map +1 -0
- package/dist/collect/lighthouse.js +111 -0
- package/dist/collect/lighthouse.js.map +1 -0
- package/dist/collect/network.d.ts +32 -0
- package/dist/collect/network.d.ts.map +1 -0
- package/dist/collect/network.js +236 -0
- package/dist/collect/network.js.map +1 -0
- package/dist/collect/orchestrator.d.ts +23 -0
- package/dist/collect/orchestrator.d.ts.map +1 -0
- package/dist/collect/orchestrator.js +350 -0
- package/dist/collect/orchestrator.js.map +1 -0
- package/dist/collect/performance.d.ts +28 -0
- package/dist/collect/performance.d.ts.map +1 -0
- package/dist/collect/performance.js +108 -0
- package/dist/collect/performance.js.map +1 -0
- package/dist/collect/runtime.d.ts +26 -0
- package/dist/collect/runtime.d.ts.map +1 -0
- package/dist/collect/runtime.js +81 -0
- package/dist/collect/runtime.js.map +1 -0
- package/dist/collect/session.d.ts +58 -0
- package/dist/collect/session.d.ts.map +1 -0
- package/dist/collect/session.js +162 -0
- package/dist/collect/session.js.map +1 -0
- package/dist/collect/trace.d.ts +40 -0
- package/dist/collect/trace.d.ts.map +1 -0
- package/dist/collect/trace.js +127 -0
- package/dist/collect/trace.js.map +1 -0
- package/dist/collect/types.d.ts +317 -0
- package/dist/collect/types.d.ts.map +1 -0
- package/dist/collect/types.js +12 -0
- package/dist/collect/types.js.map +1 -0
- package/dist/distill/insights.d.ts +67 -0
- package/dist/distill/insights.d.ts.map +1 -0
- package/dist/distill/insights.js +317 -0
- package/dist/distill/insights.js.map +1 -0
- package/dist/distill/summaries.d.ts +71 -0
- package/dist/distill/summaries.d.ts.map +1 -0
- package/dist/distill/summaries.js +165 -0
- package/dist/distill/summaries.js.map +1 -0
- package/dist/extract/critical-path.d.ts +17 -0
- package/dist/extract/critical-path.d.ts.map +1 -0
- package/dist/extract/critical-path.js +95 -0
- package/dist/extract/critical-path.js.map +1 -0
- package/dist/extract/index.d.ts +16 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +32 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/js-hotspots.d.ts +15 -0
- package/dist/extract/js-hotspots.d.ts.map +1 -0
- package/dist/extract/js-hotspots.js +22 -0
- package/dist/extract/js-hotspots.js.map +1 -0
- package/dist/extract/layout-shifts.d.ts +19 -0
- package/dist/extract/layout-shifts.d.ts.map +1 -0
- package/dist/extract/layout-shifts.js +47 -0
- package/dist/extract/layout-shifts.js.map +1 -0
- package/dist/extract/lcp-breakdown.d.ts +19 -0
- package/dist/extract/lcp-breakdown.d.ts.map +1 -0
- package/dist/extract/lcp-breakdown.js +110 -0
- package/dist/extract/lcp-breakdown.js.map +1 -0
- package/dist/extract/main-thread.d.ts +16 -0
- package/dist/extract/main-thread.d.ts.map +1 -0
- package/dist/extract/main-thread.js +41 -0
- package/dist/extract/main-thread.js.map +1 -0
- package/dist/extract/render-blocking.d.ts +16 -0
- package/dist/extract/render-blocking.d.ts.map +1 -0
- package/dist/extract/render-blocking.js +79 -0
- package/dist/extract/render-blocking.js.map +1 -0
- package/dist/extract/third-party.d.ts +15 -0
- package/dist/extract/third-party.d.ts.map +1 -0
- package/dist/extract/third-party.js +127 -0
- package/dist/extract/third-party.js.map +1 -0
- package/dist/extract/types.d.ts +183 -0
- package/dist/extract/types.d.ts.map +1 -0
- package/dist/extract/types.js +118 -0
- package/dist/extract/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +72 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +285 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/progress.d.ts +37 -0
- package/dist/mcp/progress.d.ts.map +1 -0
- package/dist/mcp/progress.js +51 -0
- package/dist/mcp/progress.js.map +1 -0
- package/dist/mcp/prompts.d.ts +57 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +225 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +48 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +149 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +34 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +452 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/types.d.ts +47 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +67 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/normalize/clock.d.ts +40 -0
- package/dist/normalize/clock.d.ts.map +1 -0
- package/dist/normalize/clock.js +96 -0
- package/dist/normalize/clock.js.map +1 -0
- package/dist/normalize/dom-ir.d.ts +16 -0
- package/dist/normalize/dom-ir.d.ts.map +1 -0
- package/dist/normalize/dom-ir.js +48 -0
- package/dist/normalize/dom-ir.js.map +1 -0
- package/dist/normalize/index.d.ts +23 -0
- package/dist/normalize/index.d.ts.map +1 -0
- package/dist/normalize/index.js +118 -0
- package/dist/normalize/index.js.map +1 -0
- package/dist/normalize/lighthouse-insights.d.ts +27 -0
- package/dist/normalize/lighthouse-insights.d.ts.map +1 -0
- package/dist/normalize/lighthouse-insights.js +318 -0
- package/dist/normalize/lighthouse-insights.js.map +1 -0
- package/dist/normalize/lighthouse-ir.d.ts +25 -0
- package/dist/normalize/lighthouse-ir.d.ts.map +1 -0
- package/dist/normalize/lighthouse-ir.js +151 -0
- package/dist/normalize/lighthouse-ir.js.map +1 -0
- package/dist/normalize/network-ir.d.ts +23 -0
- package/dist/normalize/network-ir.d.ts.map +1 -0
- package/dist/normalize/network-ir.js +180 -0
- package/dist/normalize/network-ir.js.map +1 -0
- package/dist/normalize/runtime-ir.d.ts +18 -0
- package/dist/normalize/runtime-ir.d.ts.map +1 -0
- package/dist/normalize/runtime-ir.js +114 -0
- package/dist/normalize/runtime-ir.js.map +1 -0
- package/dist/normalize/trace-ir.d.ts +20 -0
- package/dist/normalize/trace-ir.d.ts.map +1 -0
- package/dist/normalize/trace-ir.js +224 -0
- package/dist/normalize/trace-ir.js.map +1 -0
- package/dist/normalize/types.d.ts +536 -0
- package/dist/normalize/types.d.ts.map +1 -0
- package/dist/normalize/types.js +242 -0
- package/dist/normalize/types.js.map +1 -0
- package/dist/output/manifest.d.ts +44 -0
- package/dist/output/manifest.d.ts.map +1 -0
- package/dist/output/manifest.js +232 -0
- package/dist/output/manifest.js.map +1 -0
- package/dist/output/toon.d.ts +19 -0
- package/dist/output/toon.d.ts.map +1 -0
- package/dist/output/toon.js +22 -0
- package/dist/output/toon.js.map +1 -0
- package/dist/output/writer.d.ts +31 -0
- package/dist/output/writer.d.ts.map +1 -0
- package/dist/output/writer.js +51 -0
- package/dist/output/writer.js.map +1 -0
- package/dist/report/analyzer.d.ts +29 -0
- package/dist/report/analyzer.d.ts.map +1 -0
- package/dist/report/analyzer.js +330 -0
- package/dist/report/analyzer.js.map +1 -0
- package/dist/report/index.d.ts +13 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +12 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/markdown.d.ts +21 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +182 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/remediations.d.ts +42 -0
- package/dist/report/remediations.d.ts.map +1 -0
- package/dist/report/remediations.js +179 -0
- package/dist/report/remediations.js.map +1 -0
- package/dist/report/scorer.d.ts +35 -0
- package/dist/report/scorer.d.ts.map +1 -0
- package/dist/report/scorer.js +72 -0
- package/dist/report/scorer.js.map +1 -0
- package/dist/report/types.d.ts +201 -0
- package/dist/report/types.d.ts.map +1 -0
- package/dist/report/types.js +149 -0
- package/dist/report/types.js.map +1 -0
- package/dist/shared/fs-utils.d.ts +12 -0
- package/dist/shared/fs-utils.d.ts.map +1 -0
- package/dist/shared/fs-utils.js +44 -0
- package/dist/shared/fs-utils.js.map +1 -0
- package/dist/shared/types.d.ts +69 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +18 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/utils.d.ts +6 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +9 -0
- package/dist/shared/utils.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse-insights.js","sourceRoot":"","sources":["../../src/normalize/lighthouse-insights.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LighthouseIR builder from raw Lighthouse data.
|
|
3
|
+
*
|
|
4
|
+
* Converts a Lighthouse Report (LHR) into a normalized LighthouseIR with
|
|
5
|
+
* category scores, failed audits, and high-level score summary.
|
|
6
|
+
* Lighthouse values are already in their own units — no clock conversion
|
|
7
|
+
* is needed.
|
|
8
|
+
*/
|
|
9
|
+
import type { LighthouseRawData } from '../collect/types.js';
|
|
10
|
+
import type { LighthouseIR } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Build a complete LighthouseIR from raw Lighthouse data.
|
|
13
|
+
*
|
|
14
|
+
* Extracts:
|
|
15
|
+
* - categories: keyed by category ID (performance, accessibility, etc.)
|
|
16
|
+
* with title and score (0-1)
|
|
17
|
+
* - failedAudits: all audits with score < 1, including id, title,
|
|
18
|
+
* description, score, and optional numericValue
|
|
19
|
+
* - scores: top-level performance/accessibility/best-practices/seo scores
|
|
20
|
+
*
|
|
21
|
+
* @param lighthouse - Raw Lighthouse data from the LighthouseCollector
|
|
22
|
+
* @returns A fully-constructed LighthouseIR
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildLighthouseIR(lighthouse: LighthouseRawData): LighthouseIR;
|
|
25
|
+
//# sourceMappingURL=lighthouse-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse-ir.d.ts","sourceRoot":"","sources":["../../src/normalize/lighthouse-ir.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AA4FpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,iBAAiB,GAC5B,YAAY,CAkFd"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LighthouseIR builder from raw Lighthouse data.
|
|
3
|
+
*
|
|
4
|
+
* Converts a Lighthouse Report (LHR) into a normalized LighthouseIR with
|
|
5
|
+
* category scores, failed audits, and high-level score summary.
|
|
6
|
+
* Lighthouse values are already in their own units — no clock conversion
|
|
7
|
+
* is needed.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Helpers
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Narrow an unknown value to a string-keyed record */
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse LCP element details from the lcp-breakdown-insight audit.
|
|
18
|
+
*
|
|
19
|
+
* The insight audit has a `details.items` array where each item with
|
|
20
|
+
* `type === "node"` carries selector, snippet, and nodeLabel for the LCP
|
|
21
|
+
* element.
|
|
22
|
+
*/
|
|
23
|
+
function parseLcpBreakdownElement(audit) {
|
|
24
|
+
const details = isRecord(audit.details) ? audit.details : undefined;
|
|
25
|
+
if (!details)
|
|
26
|
+
return undefined;
|
|
27
|
+
const items = Array.isArray(details.items) ? details.items.filter(isRecord) : [];
|
|
28
|
+
for (const item of items) {
|
|
29
|
+
if (item.type === 'node') {
|
|
30
|
+
return {
|
|
31
|
+
selector: typeof item.selector === 'string' ? item.selector : undefined,
|
|
32
|
+
snippet: typeof item.snippet === 'string' ? item.snippet : undefined,
|
|
33
|
+
nodeLabel: typeof item.nodeLabel === 'string' ? item.nodeLabel : undefined,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse render-blocking resources from a Lighthouse audit (render-blocking-insight
|
|
41
|
+
* or render-blocking-resources). Both use the same details.items structure with
|
|
42
|
+
* url, totalBytes, wastedMs, and optional resourceType fields.
|
|
43
|
+
*/
|
|
44
|
+
function parseRenderBlockingResources(audit) {
|
|
45
|
+
const details = audit.details;
|
|
46
|
+
if (!details)
|
|
47
|
+
return undefined;
|
|
48
|
+
const items = Array.isArray(details.items) ? details.items.filter(isRecord) : [];
|
|
49
|
+
if (items.length === 0)
|
|
50
|
+
return undefined;
|
|
51
|
+
const resources = items
|
|
52
|
+
.map((item) => ({
|
|
53
|
+
url: typeof item.url === 'string' ? item.url : '',
|
|
54
|
+
totalBytes: typeof item.totalBytes === 'number' ? item.totalBytes : undefined,
|
|
55
|
+
wastedMs: typeof item.wastedMs === 'number' ? item.wastedMs : undefined,
|
|
56
|
+
resourceType: typeof item.resourceType === 'string' ? item.resourceType : undefined,
|
|
57
|
+
}))
|
|
58
|
+
.filter((r) => r.url.length > 0);
|
|
59
|
+
return resources.length > 0 ? resources : undefined;
|
|
60
|
+
}
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Main builder
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
/**
|
|
65
|
+
* Build a complete LighthouseIR from raw Lighthouse data.
|
|
66
|
+
*
|
|
67
|
+
* Extracts:
|
|
68
|
+
* - categories: keyed by category ID (performance, accessibility, etc.)
|
|
69
|
+
* with title and score (0-1)
|
|
70
|
+
* - failedAudits: all audits with score < 1, including id, title,
|
|
71
|
+
* description, score, and optional numericValue
|
|
72
|
+
* - scores: top-level performance/accessibility/best-practices/seo scores
|
|
73
|
+
*
|
|
74
|
+
* @param lighthouse - Raw Lighthouse data from the LighthouseCollector
|
|
75
|
+
* @returns A fully-constructed LighthouseIR
|
|
76
|
+
*/
|
|
77
|
+
export function buildLighthouseIR(lighthouse) {
|
|
78
|
+
const lhr = (lighthouse.lhr ?? {});
|
|
79
|
+
// 1. Extract categories
|
|
80
|
+
const categories = {};
|
|
81
|
+
const rawCategories = lhr.categories ?? {};
|
|
82
|
+
for (const [key, cat] of Object.entries(rawCategories)) {
|
|
83
|
+
if (cat && typeof cat.title === 'string') {
|
|
84
|
+
categories[key] = {
|
|
85
|
+
title: cat.title,
|
|
86
|
+
score: typeof cat.score === 'number' ? cat.score : 0,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// 2. Extract scores map from known categories
|
|
91
|
+
const scores = {
|
|
92
|
+
performance: categories['performance']?.score,
|
|
93
|
+
accessibility: categories['accessibility']?.score,
|
|
94
|
+
bestPractices: categories['best-practices']?.score,
|
|
95
|
+
seo: categories['seo']?.score,
|
|
96
|
+
};
|
|
97
|
+
// 3. Extract failed audits (score < 1)
|
|
98
|
+
const failedAudits = [];
|
|
99
|
+
const rawAudits = lhr.audits ?? {};
|
|
100
|
+
for (const [, audit] of Object.entries(rawAudits)) {
|
|
101
|
+
if (!audit)
|
|
102
|
+
continue;
|
|
103
|
+
const score = audit.score;
|
|
104
|
+
// Include audits with score < 1 (including null → treated as 0)
|
|
105
|
+
const effectiveScore = score === null || score === undefined ? 0 : score;
|
|
106
|
+
if (effectiveScore >= 1)
|
|
107
|
+
continue;
|
|
108
|
+
failedAudits.push({
|
|
109
|
+
id: audit.id ?? '',
|
|
110
|
+
title: audit.title ?? '',
|
|
111
|
+
description: audit.description ?? '',
|
|
112
|
+
score: effectiveScore,
|
|
113
|
+
numericValue: typeof audit.numericValue === 'number'
|
|
114
|
+
? audit.numericValue
|
|
115
|
+
: undefined,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// 4. Extract LCP numeric value from Lighthouse audit (for fallback in extract phase)
|
|
119
|
+
const lcpAudit = isRecord(rawAudits['largest-contentful-paint'])
|
|
120
|
+
? rawAudits['largest-contentful-paint']
|
|
121
|
+
: undefined;
|
|
122
|
+
const lcpNumericValue = lcpAudit && typeof lcpAudit.numericValue === 'number'
|
|
123
|
+
? lcpAudit.numericValue
|
|
124
|
+
: undefined;
|
|
125
|
+
// 5. Extract lcp-breakdown-insight for element details
|
|
126
|
+
const lcpBreakdownAudit = isRecord(rawAudits['lcp-breakdown-insight'])
|
|
127
|
+
? rawAudits['lcp-breakdown-insight']
|
|
128
|
+
: undefined;
|
|
129
|
+
const lcpElement = lcpBreakdownAudit
|
|
130
|
+
? parseLcpBreakdownElement(lcpBreakdownAudit)
|
|
131
|
+
: undefined;
|
|
132
|
+
// 6. Extract render-blocking resources from Lighthouse insight audits
|
|
133
|
+
// Try render-blocking-insight (v13+) first, fall back to render-blocking-resources (older)
|
|
134
|
+
const rbInsight = rawAudits['render-blocking-insight'];
|
|
135
|
+
const rbOld = !rbInsight ? rawAudits['render-blocking-resources'] : undefined;
|
|
136
|
+
const renderBlockingAudit = rbInsight ?? rbOld;
|
|
137
|
+
const renderBlockingResources = renderBlockingAudit
|
|
138
|
+
? parseRenderBlockingResources(renderBlockingAudit)
|
|
139
|
+
: undefined;
|
|
140
|
+
return {
|
|
141
|
+
categories,
|
|
142
|
+
failedAudits,
|
|
143
|
+
scores,
|
|
144
|
+
lcpNumericValue: lcpNumericValue !== undefined ? lcpNumericValue : undefined,
|
|
145
|
+
lcpElementSelector: lcpElement?.selector,
|
|
146
|
+
lcpElementSnippet: lcpElement?.snippet,
|
|
147
|
+
lcpElementNodeLabel: lcpElement?.nodeLabel,
|
|
148
|
+
renderBlockingResources,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=lighthouse-ir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse-ir.js","sourceRoot":"","sources":["../../src/normalize/lighthouse-ir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NetworkIR builder from raw CDP network data.
|
|
3
|
+
*
|
|
4
|
+
* Converts raw network request entries (from the Network domain) into a
|
|
5
|
+
* normalized NetworkIR with all timestamps in ms relative to navigationStart.
|
|
6
|
+
*/
|
|
7
|
+
import type { NetworkRawData } from '../collect/types.js';
|
|
8
|
+
import type { NetworkIR } from './types.js';
|
|
9
|
+
import { type ClockAnchor } from './clock.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build a complete NetworkIR from raw CDP network data.
|
|
12
|
+
*
|
|
13
|
+
* Maps each raw NetworkRequestEntry to a NormalizedRequest, converting
|
|
14
|
+
* timestamps from the network-monotonic-s clock domain to ms relative
|
|
15
|
+
* to navigationStart. Produces summary statistics including totals,
|
|
16
|
+
* grouping by type/priority, and critical path chain.
|
|
17
|
+
*
|
|
18
|
+
* @param network - Raw network data from the NetworkCollector
|
|
19
|
+
* @param anchor - ClockAnchor with navigationStart and firstRequestWallTime
|
|
20
|
+
* @returns A fully-constructed NetworkIR
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildNetworkIR(network: NetworkRawData, anchor: ClockAnchor): NetworkIR;
|
|
23
|
+
//# sourceMappingURL=network-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-ir.d.ts","sourceRoot":"","sources":["../../src/normalize/network-ir.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAsC,MAAM,qBAAqB,CAAC;AAC9F,OAAO,KAAK,EAAE,SAAS,EAAwG,MAAM,YAAY,CAAC;AAClJ,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAiK5D;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,GAClB,SAAS,CAiCX"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NetworkIR builder from raw CDP network data.
|
|
3
|
+
*
|
|
4
|
+
* Converts raw network request entries (from the Network domain) into a
|
|
5
|
+
* normalized NetworkIR with all timestamps in ms relative to navigationStart.
|
|
6
|
+
*/
|
|
7
|
+
import { toRelativeMs } from './clock.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Helpers
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/**
|
|
12
|
+
* Compute NormalizedRequestTiming from a raw NetworkTiming object.
|
|
13
|
+
*
|
|
14
|
+
* For dns/connect/ssl: only compute if both start and end are >= 0 (CDP
|
|
15
|
+
* convention for "not applicable"). For wait/receive: always compute as
|
|
16
|
+
* differences when timing exists.
|
|
17
|
+
*/
|
|
18
|
+
function computeTiming(timing) {
|
|
19
|
+
if (!timing) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
dns: timing.dnsStart >= 0 && timing.dnsEnd >= 0
|
|
24
|
+
? timing.dnsEnd - timing.dnsStart
|
|
25
|
+
: undefined,
|
|
26
|
+
connect: timing.connectStart >= 0 && timing.connectEnd >= 0
|
|
27
|
+
? timing.connectEnd - timing.connectStart
|
|
28
|
+
: undefined,
|
|
29
|
+
ssl: timing.sslStart >= 0 && timing.sslEnd >= 0
|
|
30
|
+
? timing.sslEnd - timing.sslStart
|
|
31
|
+
: undefined,
|
|
32
|
+
wait: timing.sendEnd - timing.sendStart,
|
|
33
|
+
receive: timing.receiveHeadersEnd - timing.sendEnd,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a critical-path initiator dependency tree from normalized requests.
|
|
38
|
+
*
|
|
39
|
+
* Uses CDP `initiator.url` to build a parent-child tree. The Document
|
|
40
|
+
* request (or first request if no Document) becomes the root. Every
|
|
41
|
+
* request without a known initiatorUrl is attached to the root.
|
|
42
|
+
*/
|
|
43
|
+
function buildCriticalPathInfo(requests) {
|
|
44
|
+
if (requests.length === 0) {
|
|
45
|
+
return {
|
|
46
|
+
tree: { url: '' },
|
|
47
|
+
depth: 0,
|
|
48
|
+
urlsOnLongestPath: [],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Build URL → request map
|
|
52
|
+
const reqMap = new Map();
|
|
53
|
+
for (const req of requests) {
|
|
54
|
+
reqMap.set(req.url, req);
|
|
55
|
+
}
|
|
56
|
+
// Find root: the Document request, or first request
|
|
57
|
+
// (requests.length > 0 is guaranteed by early return above)
|
|
58
|
+
let root = requests.find((r) => r.resourceType === 'Document') ?? requests[0];
|
|
59
|
+
// Build URL → children map
|
|
60
|
+
const childrenOf = new Map();
|
|
61
|
+
for (const req of requests) {
|
|
62
|
+
if (req.url === root.url)
|
|
63
|
+
continue;
|
|
64
|
+
const parentUrl = (req.initiatorUrl && reqMap.has(req.initiatorUrl))
|
|
65
|
+
? req.initiatorUrl
|
|
66
|
+
: root.url;
|
|
67
|
+
const existing = childrenOf.get(parentUrl) ?? [];
|
|
68
|
+
existing.push(req);
|
|
69
|
+
childrenOf.set(parentUrl, existing);
|
|
70
|
+
}
|
|
71
|
+
// Recursively build tree nodes and find longest path
|
|
72
|
+
function buildNode(url, depth) {
|
|
73
|
+
const req = reqMap.get(url);
|
|
74
|
+
const children = childrenOf.get(url) ?? [];
|
|
75
|
+
let maxChildDepth = depth;
|
|
76
|
+
let longestChildPath = [url];
|
|
77
|
+
const childNodes = [];
|
|
78
|
+
for (const child of children) {
|
|
79
|
+
const result = buildNode(child.url, depth + 1);
|
|
80
|
+
childNodes.push(result.node);
|
|
81
|
+
if (result.maxDepth > maxChildDepth) {
|
|
82
|
+
maxChildDepth = result.maxDepth;
|
|
83
|
+
longestChildPath = [url, ...result.longestPath];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
node: {
|
|
88
|
+
url,
|
|
89
|
+
durationMs: req ? req.duration : undefined,
|
|
90
|
+
children: childNodes.length > 0 ? childNodes : undefined,
|
|
91
|
+
},
|
|
92
|
+
maxDepth: maxChildDepth,
|
|
93
|
+
longestPath: longestChildPath,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const result = buildNode(root.url, 1);
|
|
97
|
+
return {
|
|
98
|
+
tree: result.node,
|
|
99
|
+
depth: result.maxDepth,
|
|
100
|
+
urlsOnLongestPath: result.longestPath,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build Summary statistics from all normalized requests.
|
|
105
|
+
*/
|
|
106
|
+
function buildSummary(requests) {
|
|
107
|
+
const totalRequests = requests.length;
|
|
108
|
+
if (totalRequests === 0) {
|
|
109
|
+
return {
|
|
110
|
+
totalRequests: 0,
|
|
111
|
+
totalBytes: 0,
|
|
112
|
+
byType: {},
|
|
113
|
+
byPriority: {},
|
|
114
|
+
criticalPath: { tree: { url: '' }, depth: 0, urlsOnLongestPath: [] },
|
|
115
|
+
longestChain: { url: '', length: 0 },
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const totalBytes = requests.reduce((sum, r) => sum + r.bytes, 0);
|
|
119
|
+
const byType = {};
|
|
120
|
+
const byPriority = {};
|
|
121
|
+
for (const req of requests) {
|
|
122
|
+
byType[req.resourceType] = (byType[req.resourceType] ?? 0) + 1;
|
|
123
|
+
byPriority[req.priority] = (byPriority[req.priority] ?? 0) + 1;
|
|
124
|
+
}
|
|
125
|
+
// Build initiator dependency tree
|
|
126
|
+
const criticalPath = buildCriticalPathInfo(requests);
|
|
127
|
+
// Longest chain: request with max duration
|
|
128
|
+
const longest = requests.reduce((max, r) => r.duration > max.duration ? r : max);
|
|
129
|
+
return {
|
|
130
|
+
totalRequests,
|
|
131
|
+
totalBytes,
|
|
132
|
+
byType,
|
|
133
|
+
byPriority,
|
|
134
|
+
criticalPath,
|
|
135
|
+
longestChain: { url: longest.url, length: longest.duration },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// Main builder
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
/**
|
|
142
|
+
* Build a complete NetworkIR from raw CDP network data.
|
|
143
|
+
*
|
|
144
|
+
* Maps each raw NetworkRequestEntry to a NormalizedRequest, converting
|
|
145
|
+
* timestamps from the network-monotonic-s clock domain to ms relative
|
|
146
|
+
* to navigationStart. Produces summary statistics including totals,
|
|
147
|
+
* grouping by type/priority, and critical path chain.
|
|
148
|
+
*
|
|
149
|
+
* @param network - Raw network data from the NetworkCollector
|
|
150
|
+
* @param anchor - ClockAnchor with navigationStart and firstRequestWallTime
|
|
151
|
+
* @returns A fully-constructed NetworkIR
|
|
152
|
+
*/
|
|
153
|
+
export function buildNetworkIR(network, anchor) {
|
|
154
|
+
const requests = (network.requests ?? []).map((entry) => {
|
|
155
|
+
const timing = entry.response?.timing;
|
|
156
|
+
const requestTime = timing?.requestTime;
|
|
157
|
+
const startTime = requestTime !== undefined && requestTime !== null
|
|
158
|
+
? toRelativeMs(requestTime, 'network-monotonic-s', anchor)
|
|
159
|
+
: 0;
|
|
160
|
+
const endTime = startTime + (timing?.receiveHeadersEnd ?? 0);
|
|
161
|
+
return {
|
|
162
|
+
url: entry.url,
|
|
163
|
+
method: entry.method,
|
|
164
|
+
resourceType: entry.type ?? 'Other',
|
|
165
|
+
statusCode: entry.response?.status ?? 0,
|
|
166
|
+
startTime,
|
|
167
|
+
endTime,
|
|
168
|
+
duration: endTime - startTime,
|
|
169
|
+
bytes: entry.response?.encodedDataLength ?? 0,
|
|
170
|
+
priority: entry.request?.initialPriority ?? 'Low',
|
|
171
|
+
initiator: entry.initiator?.type ?? 'other',
|
|
172
|
+
initiatorUrl: entry.initiator?.url,
|
|
173
|
+
failed: !!(entry.failed || entry.errorText),
|
|
174
|
+
timing: computeTiming(timing),
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
const summary = buildSummary(requests);
|
|
178
|
+
return { requests, summary };
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=network-ir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-ir.js","sourceRoot":"","sources":["../../src/normalize/network-ir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeIR builder from runtime and console raw data.
|
|
3
|
+
*
|
|
4
|
+
* Converts CDP runtime metrics and console entries into a normalized
|
|
5
|
+
* RuntimeIR structure with heap stats, execution contexts, event loop
|
|
6
|
+
* analysis, and hydration cost estimates.
|
|
7
|
+
*/
|
|
8
|
+
import type { RuntimeIR } from './types.js';
|
|
9
|
+
import type { RuntimeRawData, ConsoleRawData } from '../collect/types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build a complete RuntimeIR from runtime and console raw data.
|
|
12
|
+
*
|
|
13
|
+
* @param runtime - Raw runtime data from the RuntimeCollector
|
|
14
|
+
* @param console - Raw console data from the ConsoleCollector
|
|
15
|
+
* @returns A fully-constructed RuntimeIR
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildRuntimeIR(runtime: RuntimeRawData, console: ConsoleRawData): RuntimeIR;
|
|
18
|
+
//# sourceMappingURL=runtime-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-ir.d.ts","sourceRoot":"","sources":["../../src/normalize/runtime-ir.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAmE,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAgB,MAAM,qBAAqB,CAAC;AA2FxF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,GACtB,SAAS,CAyBX"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeIR builder from runtime and console raw data.
|
|
3
|
+
*
|
|
4
|
+
* Converts CDP runtime metrics and console entries into a normalized
|
|
5
|
+
* RuntimeIR structure with heap stats, execution contexts, event loop
|
|
6
|
+
* analysis, and hydration cost estimates.
|
|
7
|
+
*/
|
|
8
|
+
import { RuntimeIRSchema } from './types.js';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Helpers
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Compute event loop statistics from console entry inter-arrival times.
|
|
14
|
+
*
|
|
15
|
+
* Uses the time delta between consecutive console entries as a proxy for
|
|
16
|
+
* event loop blocking — gaps > 50ms are treated as blocking events.
|
|
17
|
+
*
|
|
18
|
+
* @param entries - Console entries sorted by timestamp
|
|
19
|
+
* @returns EventLoopStats or undefined if fewer than 2 entries or no blocking found
|
|
20
|
+
*/
|
|
21
|
+
function computeEventLoopStats(entries) {
|
|
22
|
+
if (entries.length < 2)
|
|
23
|
+
return undefined;
|
|
24
|
+
let totalBlockingDuration = 0;
|
|
25
|
+
let longTasks = 0;
|
|
26
|
+
let maxBlockingDuration = 0;
|
|
27
|
+
for (let i = 1; i < entries.length; i++) {
|
|
28
|
+
const prev = entries[i - 1];
|
|
29
|
+
const curr = entries[i];
|
|
30
|
+
if (!prev || !curr)
|
|
31
|
+
continue;
|
|
32
|
+
const diff = curr.timestamp - prev.timestamp;
|
|
33
|
+
if (diff > 50) {
|
|
34
|
+
totalBlockingDuration += diff;
|
|
35
|
+
longTasks++;
|
|
36
|
+
if (diff > maxBlockingDuration) {
|
|
37
|
+
maxBlockingDuration = diff;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (longTasks === 0)
|
|
42
|
+
return undefined;
|
|
43
|
+
return { totalBlockingDuration, longTasks, maxBlockingDuration };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compute hydration cost estimate from execution contexts and console entries.
|
|
47
|
+
*
|
|
48
|
+
* - bootupTime: heuristic baseline based on number of execution contexts
|
|
49
|
+
* - evaluatedScripts: console entries indicating script evaluation activity
|
|
50
|
+
*
|
|
51
|
+
* @param contexts - Normalized execution contexts
|
|
52
|
+
* @param entries - Raw console entries
|
|
53
|
+
* @returns HydrationCost estimate
|
|
54
|
+
*/
|
|
55
|
+
function computeHydrationCost(contexts, entries) {
|
|
56
|
+
const bootupTime = contexts.length * 50;
|
|
57
|
+
const evaluatedScripts = entries.filter((e) => e.type === 'debug' ||
|
|
58
|
+
e.args.some((arg) => typeof arg === 'string' &&
|
|
59
|
+
(arg.toLowerCase().includes('evaluate') ||
|
|
60
|
+
arg.toLowerCase().includes('script') ||
|
|
61
|
+
arg.toLowerCase().includes('render')))).length;
|
|
62
|
+
return { bootupTime, evaluatedScripts };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Map raw runtime stats to normalized RuntimeIRStats.
|
|
66
|
+
*
|
|
67
|
+
* DomRawData.stats.jsHeapSize maps to totalJSHeapSize.
|
|
68
|
+
* usedJSHeapSize is estimated as 60% of total (since CDP provides only
|
|
69
|
+
* the total JS heap size, not the breakdown).
|
|
70
|
+
* jsHeapSizeLimit is not available from the raw data and is omitted.
|
|
71
|
+
*
|
|
72
|
+
* @param stats - Raw runtime stats from RuntimeCollector
|
|
73
|
+
* @returns Normalized RuntimeIRStats
|
|
74
|
+
*/
|
|
75
|
+
function buildJSHeapStats(stats) {
|
|
76
|
+
if (!stats)
|
|
77
|
+
return undefined;
|
|
78
|
+
return {
|
|
79
|
+
totalJSHeapSize: stats.jsHeapSize,
|
|
80
|
+
usedJSHeapSize: Math.round(stats.jsHeapSize * 0.6),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Main builder
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
/**
|
|
87
|
+
* Build a complete RuntimeIR from runtime and console raw data.
|
|
88
|
+
*
|
|
89
|
+
* @param runtime - Raw runtime data from the RuntimeCollector
|
|
90
|
+
* @param console - Raw console data from the ConsoleCollector
|
|
91
|
+
* @returns A fully-constructed RuntimeIR
|
|
92
|
+
*/
|
|
93
|
+
export function buildRuntimeIR(runtime, console) {
|
|
94
|
+
// 1. Execution contexts: pass through id, origin, name
|
|
95
|
+
const executionContexts = runtime.contexts.map((ctx) => ({
|
|
96
|
+
id: ctx.id,
|
|
97
|
+
origin: ctx.origin,
|
|
98
|
+
name: ctx.name,
|
|
99
|
+
}));
|
|
100
|
+
// 2. JS heap stats
|
|
101
|
+
const jsHeapStats = buildJSHeapStats(runtime.stats);
|
|
102
|
+
// 3. Event loop stats from console entry inter-arrival times
|
|
103
|
+
const eventLoopStats = computeEventLoopStats(console.entries ?? []);
|
|
104
|
+
// 4. Hydration cost estimate
|
|
105
|
+
const hydrationCost = computeHydrationCost(executionContexts, console.entries ?? []);
|
|
106
|
+
const result = {
|
|
107
|
+
jsHeapStats,
|
|
108
|
+
executionContexts,
|
|
109
|
+
eventLoopStats,
|
|
110
|
+
hydrationCost,
|
|
111
|
+
};
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=runtime-ir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-ir.js","sourceRoot":"","sources":["../../src/normalize/runtime-ir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PerformanceIR builder from trace and performance raw data.
|
|
3
|
+
*
|
|
4
|
+
* Converts CDP trace events and performance metrics into a normalized
|
|
5
|
+
* PerformanceIR structure with all timestamps in ms relative to
|
|
6
|
+
* navigationStart.
|
|
7
|
+
*/
|
|
8
|
+
import type { TraceRawData, PerformanceRawData } from '../collect/types.js';
|
|
9
|
+
import type { PerformanceIR } from './types.js';
|
|
10
|
+
import type { ClockAnchor } from './clock.js';
|
|
11
|
+
/**
|
|
12
|
+
* Build a complete PerformanceIR from trace and performance raw data.
|
|
13
|
+
*
|
|
14
|
+
* @param trace - Raw trace events from the TraceCollector
|
|
15
|
+
* @param perf - Raw performance metrics from the PerformanceCollector
|
|
16
|
+
* @param anchor - ClockAnchor with navigationStart time
|
|
17
|
+
* @returns A fully-constructed PerformanceIR
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildPerformanceIR(trace: TraceRawData, perf: PerformanceRawData, anchor: ClockAnchor): PerformanceIR;
|
|
20
|
+
//# sourceMappingURL=trace-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-ir.d.ts","sourceRoot":"","sources":["../../src/normalize/trace-ir.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAsE,MAAM,YAAY,CAAC;AAEpH,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,YAAY,CAAC;AA2N3D;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,WAAW,GAClB,aAAa,CA4Bf"}
|