@wenathlan/extension 1.1.46 → 1.1.47
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/README.md +5 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +570 -11
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +52 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +18 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/profilers.d.ts +167 -0
- package/dist/profilers.d.ts.map +1 -0
- package/dist/protocol.d.ts +33 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/types.d.ts +131 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +913 -14
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +144 -3
- package/extension/dist/pagebridge.js.map +4 -4
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +10 -6
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +159 -2
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +1 -1
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -921,6 +921,232 @@ function streamsummaries(raw) {
|
|
|
921
921
|
});
|
|
922
922
|
}
|
|
923
923
|
|
|
924
|
+
// profilers.ts
|
|
925
|
+
var profilerkinds = ["measureflow", "heapshot", "trackmemory", "profilecpu", "watchshifts", "traceload", "annotatetrace", "replaytrace", "capturesourcemaps"];
|
|
926
|
+
var flowmetricnames = ["navigation", "paint", "lcp", "fid", "interaction", "blocking"];
|
|
927
|
+
var tracecategories = ["navigation", "scripting", "rendering", "painting", "loading", "network"];
|
|
928
|
+
function attachtargetof(value) {
|
|
929
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
930
|
+
const entry = value;
|
|
931
|
+
const kinds = ["page", "iframe", "worker", "serviceworker"];
|
|
932
|
+
const kind = typeof entry.kind === "string" && kinds.includes(entry.kind) ? entry.kind : void 0;
|
|
933
|
+
const url = typeof entry.url === "string" && entry.url.trim() ? entry.url.trim() : void 0;
|
|
934
|
+
if (kind === void 0 || url === void 0) return void 0;
|
|
935
|
+
if (kind !== "page" && !/^https:\/\//.test(url)) return void 0;
|
|
936
|
+
return { kind, url };
|
|
937
|
+
}
|
|
938
|
+
function flowspecof(value) {
|
|
939
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
940
|
+
const entry = value;
|
|
941
|
+
const prefix = typeof entry.prefix === "string" && entry.prefix.trim() ? entry.prefix.trim() : void 0;
|
|
942
|
+
const steps = Array.isArray(entry.steps) ? entry.steps.filter((step) => typeof step === "string" && step.trim().length > 0) : [];
|
|
943
|
+
const metrics = Array.isArray(entry.metrics) ? entry.metrics.filter((metric) => typeof metric === "string" && flowmetricnames.includes(metric)) : [];
|
|
944
|
+
if (prefix === void 0 || steps.length === 0 || metrics.length === 0) return void 0;
|
|
945
|
+
return { prefix, steps, metrics };
|
|
946
|
+
}
|
|
947
|
+
function stepwindows(spec, marks) {
|
|
948
|
+
const windows = [];
|
|
949
|
+
for (const stepid of spec.steps) {
|
|
950
|
+
const start = marks.find((mark) => mark.type === "mark" && mark.name === `${spec.prefix}:${stepid}:start`);
|
|
951
|
+
const end = marks.find((mark) => mark.type === "mark" && mark.name === `${spec.prefix}:${stepid}:end`);
|
|
952
|
+
if (start === void 0 || end === void 0) continue;
|
|
953
|
+
windows.push({ stepid, start: start.start, end: Math.max(end.start, start.start) });
|
|
954
|
+
}
|
|
955
|
+
return windows;
|
|
956
|
+
}
|
|
957
|
+
function measure(input) {
|
|
958
|
+
const metrics = [];
|
|
959
|
+
const windows = stepwindows(input.spec, input.entries.filter((entry) => entry.type === "mark"));
|
|
960
|
+
const stepsof = (start, end) => windows.filter((window) => window.end >= start && window.start <= end).map((window) => window.stepid);
|
|
961
|
+
const push = (name, start, end, steps) => {
|
|
962
|
+
if (!input.spec.metrics.includes(name)) return;
|
|
963
|
+
metrics.push({ id: `${input.runid}-${input.stepid}-${name}-${metrics.length}`, runid: input.runid, stepid: input.stepid, name, start, end, duration: Math.max(0, end - start), steps, at: input.now });
|
|
964
|
+
};
|
|
965
|
+
const navigation = input.entries.find((entry) => entry.type === "navigation");
|
|
966
|
+
if (navigation !== void 0) push("navigation", navigation.start, navigation.start + navigation.duration, stepsof(navigation.start, navigation.start + navigation.duration));
|
|
967
|
+
for (const paint of input.entries.filter((entry) => entry.type === "paint")) {
|
|
968
|
+
if (!input.spec.metrics.includes("paint")) break;
|
|
969
|
+
push("paint", paint.start, paint.start + paint.duration, stepsof(paint.start, paint.start + paint.duration));
|
|
970
|
+
}
|
|
971
|
+
const lcps = input.entries.filter((entry) => entry.type === "largest-contentful-paint");
|
|
972
|
+
const lcp = lcps.length > 0 ? lcps.reduce((largest, entry) => entry.start > largest.start ? entry : largest) : void 0;
|
|
973
|
+
if (lcp !== void 0) push("lcp", lcp.start, lcp.start + lcp.duration, stepsof(lcp.start, lcp.start + lcp.duration));
|
|
974
|
+
const firstinput = input.entries.find((entry) => entry.type === "first-input");
|
|
975
|
+
if (firstinput !== void 0) push("fid", firstinput.start, firstinput.start + firstinput.duration, stepsof(firstinput.start, firstinput.start + firstinput.duration));
|
|
976
|
+
const interactions = input.entries.filter((entry) => entry.type === "event");
|
|
977
|
+
if (interactions.length > 0) {
|
|
978
|
+
const start = interactions.reduce((earliest, entry) => entry.start < earliest.start ? entry : earliest).start;
|
|
979
|
+
const end = interactions.reduce((latest, entry) => entry.start + entry.duration > latest ? entry.start + entry.duration : latest, start);
|
|
980
|
+
push("interaction", start, end, stepsof(start, end));
|
|
981
|
+
}
|
|
982
|
+
for (const window of windows) {
|
|
983
|
+
if (!input.spec.metrics.includes("blocking")) break;
|
|
984
|
+
const blocking = input.entries.filter((entry) => entry.type === "longtask" && entry.start >= window.start && entry.start <= window.end).reduce((total, entry) => total + Math.max(0, entry.duration - 50), 0);
|
|
985
|
+
metrics.push({ id: `${input.runid}-${input.stepid}-blocking-${window.stepid}`, runid: input.runid, stepid: input.stepid, name: "blocking", start: window.start, end: window.end, duration: blocking, steps: [window.stepid], at: input.now });
|
|
986
|
+
}
|
|
987
|
+
return metrics;
|
|
988
|
+
}
|
|
989
|
+
function heapintervalallowed(lastcapturedat, interval, now) {
|
|
990
|
+
if (interval === void 0 || lastcapturedat === void 0) return true;
|
|
991
|
+
return now - lastcapturedat >= interval;
|
|
992
|
+
}
|
|
993
|
+
function heapsnap(input) {
|
|
994
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, origin: input.origin, bytesize: input.usedbytes, nodecount: input.nodecount, capturedat: input.now };
|
|
995
|
+
}
|
|
996
|
+
function growsampleof(input) {
|
|
997
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, usedbytes: input.usedbytes, limitbytes: input.limitbytes, at: input.now };
|
|
998
|
+
}
|
|
999
|
+
function growthtrend(input) {
|
|
1000
|
+
const ordered = [...input.samples].sort((left, right) => left.at - right.at);
|
|
1001
|
+
const first = ordered[0];
|
|
1002
|
+
const last = ordered[ordered.length - 1];
|
|
1003
|
+
const computed = first !== void 0 && last !== void 0 && last.at > first.at ? (last.usedbytes - first.usedbytes) / (last.at - first.at) : 0;
|
|
1004
|
+
const flaggedsteps = [];
|
|
1005
|
+
for (let index = 1; index < ordered.length; index += 1) {
|
|
1006
|
+
const previous = ordered[index - 1];
|
|
1007
|
+
const current = ordered[index];
|
|
1008
|
+
if (previous === void 0 || current === void 0) continue;
|
|
1009
|
+
const growth = current.at > previous.at ? (current.usedbytes - previous.usedbytes) / (current.at - previous.at) : 0;
|
|
1010
|
+
if (growth > input.slope && !flaggedsteps.includes(current.stepid)) flaggedsteps.push(current.stepid);
|
|
1011
|
+
}
|
|
1012
|
+
return { runid: input.runid, slope: computed, samples: ordered.length, flaggedsteps, at: input.now };
|
|
1013
|
+
}
|
|
1014
|
+
function cpusnap(input) {
|
|
1015
|
+
const ranked = /* @__PURE__ */ new Map();
|
|
1016
|
+
for (const sample of input.samples) ranked.set(sample.name, (ranked.get(sample.name) ?? 0) + sample.time);
|
|
1017
|
+
const hotfunctions = [...ranked.entries()].sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])).map((entry) => entry[0]);
|
|
1018
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, origin: input.origin, duration: input.duration, samplecount: input.samples.length, hotfunctions, at: input.now };
|
|
1019
|
+
}
|
|
1020
|
+
function shiftentryof(value) {
|
|
1021
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1022
|
+
const entry = value;
|
|
1023
|
+
const score = typeof entry.score === "number" && Number.isFinite(entry.score) && entry.score >= 0 ? entry.score : void 0;
|
|
1024
|
+
const starttime = typeof entry.starttime === "number" && Number.isFinite(entry.starttime) ? entry.starttime : void 0;
|
|
1025
|
+
if (score === void 0 || starttime === void 0) return void 0;
|
|
1026
|
+
const selectors = Array.isArray(entry.selectors) ? entry.selectors.filter((selector) => typeof selector === "string" && selector.trim().length > 0) : [];
|
|
1027
|
+
return { id: typeof entry.id === "string" ? entry.id : "", runid: typeof entry.runid === "string" ? entry.runid : "", stepid: typeof entry.stepid === "string" ? entry.stepid : "", score, starttime, selectors, at: typeof entry.at === "number" ? entry.at : starttime };
|
|
1028
|
+
}
|
|
1029
|
+
function tracestart(input) {
|
|
1030
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, origin: input.origin, categories: [...new Set(input.categories)], bytesize: 0, events: 0, annotations: [], startedat: input.now, endedat: input.now };
|
|
1031
|
+
}
|
|
1032
|
+
function tracetofile(trace, events) {
|
|
1033
|
+
const payload = { devthinktrace: "1.1.47", runid: trace.runid, origin: trace.origin, categories: trace.categories, startedat: trace.startedat, endedat: trace.endedat, annotations: trace.annotations, traceevents: events.map((event) => ({ name: event.name, cat: event.category, offset: event.offset })) };
|
|
1034
|
+
const content = JSON.stringify(payload);
|
|
1035
|
+
return { content, bytesize: content.length, events: events.length };
|
|
1036
|
+
}
|
|
1037
|
+
function annotationof(value) {
|
|
1038
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1039
|
+
const entry = value;
|
|
1040
|
+
const stepid = typeof entry.stepid === "string" && entry.stepid.trim() ? entry.stepid.trim() : void 0;
|
|
1041
|
+
const label = typeof entry.label === "string" && entry.label.trim() ? entry.label.trim() : void 0;
|
|
1042
|
+
if (stepid === void 0 || label === void 0) return void 0;
|
|
1043
|
+
const offset = typeof entry.offset === "number" && Number.isFinite(entry.offset) && entry.offset >= 0 ? entry.offset : 0;
|
|
1044
|
+
return { stepid, label, offset };
|
|
1045
|
+
}
|
|
1046
|
+
function annotatetrace(input) {
|
|
1047
|
+
const aligned = input.annotations.map((annotation) => {
|
|
1048
|
+
const entry = input.timeline.find((item) => item.stepid === annotation.stepid);
|
|
1049
|
+
if (entry === void 0) return annotation;
|
|
1050
|
+
return { ...annotation, offset: Math.max(0, entry.time - input.trace.startedat) };
|
|
1051
|
+
});
|
|
1052
|
+
return { ...input.trace, annotations: aligned, endedat: Math.max(input.trace.endedat, input.now) };
|
|
1053
|
+
}
|
|
1054
|
+
function replaytrace(content) {
|
|
1055
|
+
let parsed;
|
|
1056
|
+
try {
|
|
1057
|
+
parsed = JSON.parse(content);
|
|
1058
|
+
} catch {
|
|
1059
|
+
throw new Error("The trace file is not valid json.");
|
|
1060
|
+
}
|
|
1061
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("The trace file is not a json object.");
|
|
1062
|
+
const record2 = parsed;
|
|
1063
|
+
const runid = typeof record2.runid === "string" ? record2.runid : "";
|
|
1064
|
+
const annotations = Array.isArray(record2.annotations) ? record2.annotations.flatMap((item) => {
|
|
1065
|
+
const annotation = annotationof(item);
|
|
1066
|
+
return annotation !== void 0 ? [annotation] : [];
|
|
1067
|
+
}) : [];
|
|
1068
|
+
const rawevents = Array.isArray(record2.traceevents) ? record2.traceevents : [];
|
|
1069
|
+
const categories = {};
|
|
1070
|
+
const events = rawevents.flatMap((item) => {
|
|
1071
|
+
if (!item || typeof item !== "object") return [];
|
|
1072
|
+
const entry = item;
|
|
1073
|
+
if (typeof entry.name !== "string" || typeof entry.cat !== "string" || typeof entry.offset !== "number") return [];
|
|
1074
|
+
const offset = entry.offset;
|
|
1075
|
+
categories[entry.cat] = (categories[entry.cat] ?? 0) + 1;
|
|
1076
|
+
const annotation = annotations.find((candidate) => Math.abs(candidate.offset - offset) < 1);
|
|
1077
|
+
return [{ name: entry.name, category: entry.cat, offset, ...annotation !== void 0 ? { stepid: annotation.stepid } : {} }];
|
|
1078
|
+
});
|
|
1079
|
+
return { traceid: typeof record2.id === "string" ? record2.id : "", runid, categories, events, annotations };
|
|
1080
|
+
}
|
|
1081
|
+
function mapurlof(scripturl, source) {
|
|
1082
|
+
const match = /[#@]\s*sourceMappingURL=(\S+)/.exec(source);
|
|
1083
|
+
if (match === null || match[1] === void 0) return void 0;
|
|
1084
|
+
try {
|
|
1085
|
+
return new URL(match[1], scripturl).toString();
|
|
1086
|
+
} catch {
|
|
1087
|
+
return void 0;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
function capturesourcemaps(input) {
|
|
1091
|
+
return input.scripts.flatMap((script) => {
|
|
1092
|
+
const mapurl = mapurlof(script.url, script.source);
|
|
1093
|
+
if (mapurl === void 0) return [];
|
|
1094
|
+
return [{ id: `${input.runid}-${script.url}`, runid: input.runid, stepid: input.stepid, origin: input.origin, scripturl: script.url, mapurl, parsed: false, at: input.now }];
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
function decodevlq(segment) {
|
|
1098
|
+
const values = [];
|
|
1099
|
+
let shift = 0;
|
|
1100
|
+
let value = 0;
|
|
1101
|
+
for (const character of segment) {
|
|
1102
|
+
const digit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(character);
|
|
1103
|
+
if (digit < 0) return void 0;
|
|
1104
|
+
value += (digit & 31) << shift;
|
|
1105
|
+
shift += 5;
|
|
1106
|
+
if ((digit & 32) === 0) {
|
|
1107
|
+
const negative = (value & 1) === 1;
|
|
1108
|
+
values.push(negative ? -(value >>> 1) : value >>> 1);
|
|
1109
|
+
value = 0;
|
|
1110
|
+
shift = 0;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
return values.length > 0 ? values : void 0;
|
|
1114
|
+
}
|
|
1115
|
+
function rewritesourcelocation(input, map) {
|
|
1116
|
+
const sources = Array.isArray(map.sources) ? map.sources.filter((source2) => typeof source2 === "string") : [];
|
|
1117
|
+
if (sources.length === 0 || typeof map.mappings !== "string" || map.mappings.length === 0) return void 0;
|
|
1118
|
+
const lines = map.mappings.split(";");
|
|
1119
|
+
if (input.line >= lines.length) return void 0;
|
|
1120
|
+
let sourceindex = 0;
|
|
1121
|
+
let sourceline = 0;
|
|
1122
|
+
for (let line = 0; line <= input.line; line += 1) {
|
|
1123
|
+
const linemappings = lines[line];
|
|
1124
|
+
if (linemappings === void 0) continue;
|
|
1125
|
+
const first = linemappings.split(",")[0] ?? "";
|
|
1126
|
+
if (first.length === 0) continue;
|
|
1127
|
+
const values = decodevlq(first);
|
|
1128
|
+
if (values === void 0 || values.length < 4) continue;
|
|
1129
|
+
sourceindex = Math.max(0, sourceindex + (values[1] ?? 0));
|
|
1130
|
+
sourceline = Math.max(0, sourceline + (values[2] ?? 0));
|
|
1131
|
+
}
|
|
1132
|
+
const targetmappings = lines[input.line];
|
|
1133
|
+
const target = targetmappings !== void 0 ? targetmappings.split(",")[0] ?? "" : "";
|
|
1134
|
+
if (target.length === 0) return void 0;
|
|
1135
|
+
const source = sources[Math.min(sources.length - 1, sourceindex)];
|
|
1136
|
+
if (source === void 0) return void 0;
|
|
1137
|
+
return { url: source, line: sourceline };
|
|
1138
|
+
}
|
|
1139
|
+
function expireprofilerecords(input) {
|
|
1140
|
+
const retention = input.retention;
|
|
1141
|
+
if (retention === void 0) return { heaps: input.heaps, profiles: input.profiles, traces: input.traces };
|
|
1142
|
+
const expired = (at) => input.now - at > retention;
|
|
1143
|
+
return {
|
|
1144
|
+
heaps: input.heaps.map((heap) => expired(heap.capturedat) && heap.bytesexpired !== true ? { ...heap, bytesexpired: true } : heap),
|
|
1145
|
+
profiles: input.profiles.map((profile) => expired(profile.at) && profile.samplesexpired !== true ? { ...profile, samplesexpired: true } : profile),
|
|
1146
|
+
traces: input.traces.map((trace) => expired(trace.endedat) && trace.bytesexpired !== true ? { ...trace, bytesexpired: true } : trace)
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
|
|
924
1150
|
// memory.ts
|
|
925
1151
|
var sessionmemory = class {
|
|
926
1152
|
constructor(adapter) {
|
|
@@ -2164,6 +2390,133 @@ var sessionmemory = class {
|
|
|
2164
2390
|
async getlevelsummaries() {
|
|
2165
2391
|
return await this.adapter.get("levelsummaries") ?? [];
|
|
2166
2392
|
}
|
|
2393
|
+
/** Stores one measured flow metric of the run beside its step span; the flow series stays per run. */
|
|
2394
|
+
async addflowmetric(metric) {
|
|
2395
|
+
const records = await this.getflowmetrics();
|
|
2396
|
+
await this.adapter.set("flowmetrics", [metric, ...records]);
|
|
2397
|
+
}
|
|
2398
|
+
/** Returns every stored flow metric, newest first. */
|
|
2399
|
+
async getflowmetrics() {
|
|
2400
|
+
return await this.adapter.get("flowmetrics") ?? [];
|
|
2401
|
+
}
|
|
2402
|
+
/** Returns the flow metrics of one run, newest first. */
|
|
2403
|
+
async listflowmetrics(runid) {
|
|
2404
|
+
const records = await this.getflowmetrics();
|
|
2405
|
+
return records.filter((metric) => metric.runid === runid);
|
|
2406
|
+
}
|
|
2407
|
+
/** Stores one heap snapshot record with its byte and node counts; the user configured profile retention window expires the heavy snapshot bytes while the counts survive. */
|
|
2408
|
+
async setheaprecord(heap) {
|
|
2409
|
+
const records = (await this.adapter.get("heaprecords") ?? []).filter((item) => item.id !== heap.id);
|
|
2410
|
+
const retention = (await this.getsettings())?.profileretention;
|
|
2411
|
+
const { heaps } = expireprofilerecords({ heaps: [heap, ...records], profiles: [], traces: [], retention, now: Date.now() });
|
|
2412
|
+
await this.adapter.set("heaprecords", heaps);
|
|
2413
|
+
}
|
|
2414
|
+
/** Returns every stored heap snapshot record, newest first. */
|
|
2415
|
+
async getheaprecords() {
|
|
2416
|
+
return await this.adapter.get("heaprecords") ?? [];
|
|
2417
|
+
}
|
|
2418
|
+
/** Stores one heap growth sample taken beside a step. */
|
|
2419
|
+
async addgrowsample(sample) {
|
|
2420
|
+
const records = await this.adapter.get("growsamples") ?? [];
|
|
2421
|
+
await this.adapter.set("growsamples", [sample, ...records]);
|
|
2422
|
+
}
|
|
2423
|
+
/** Returns every stored heap growth sample, newest first. */
|
|
2424
|
+
async getgrowsamples() {
|
|
2425
|
+
return await this.adapter.get("growsamples") ?? [];
|
|
2426
|
+
}
|
|
2427
|
+
/** Returns the heap growth samples of one run, newest first. */
|
|
2428
|
+
async listgrowsamples(runid) {
|
|
2429
|
+
const records = await this.getgrowsamples();
|
|
2430
|
+
return records.filter((sample) => sample.runid === runid);
|
|
2431
|
+
}
|
|
2432
|
+
/** Stores one computed heap growth trend of a run with its slope and flagged steps, replacing the previous trend of the run. */
|
|
2433
|
+
async settrend(trend) {
|
|
2434
|
+
const records = await this.adapter.get("memorytrends") ?? [];
|
|
2435
|
+
await this.adapter.set("memorytrends", [trend, ...records.filter((item) => item.runid !== trend.runid)]);
|
|
2436
|
+
}
|
|
2437
|
+
/** Returns every stored heap growth trend, newest first. */
|
|
2438
|
+
async gettrends() {
|
|
2439
|
+
return await this.adapter.get("memorytrends") ?? [];
|
|
2440
|
+
}
|
|
2441
|
+
/** Stores one cpu profile record with its sample count and hot function list; the profile retention window expires the heavy sample payload while the counts and hot functions survive. */
|
|
2442
|
+
async setcpuprofile(profile) {
|
|
2443
|
+
const records = (await this.adapter.get("cpuprofiles") ?? []).filter((item) => item.id !== profile.id);
|
|
2444
|
+
const retention = (await this.getsettings())?.profileretention;
|
|
2445
|
+
const { profiles } = expireprofilerecords({ heaps: [], profiles: [profile, ...records], traces: [], retention, now: Date.now() });
|
|
2446
|
+
await this.adapter.set("cpuprofiles", profiles);
|
|
2447
|
+
}
|
|
2448
|
+
/** Returns every stored cpu profile record, newest first. */
|
|
2449
|
+
async getcpuprofiles() {
|
|
2450
|
+
return await this.adapter.get("cpuprofiles") ?? [];
|
|
2451
|
+
}
|
|
2452
|
+
/** Stores one layout shift entry with its score and impacted selectors. */
|
|
2453
|
+
async addshiftentry(entry) {
|
|
2454
|
+
const records = await this.adapter.get("shiftentries") ?? [];
|
|
2455
|
+
await this.adapter.set("shiftentries", [entry, ...records]);
|
|
2456
|
+
}
|
|
2457
|
+
/** Returns every stored layout shift entry, newest first. */
|
|
2458
|
+
async getshiftentries() {
|
|
2459
|
+
return await this.adapter.get("shiftentries") ?? [];
|
|
2460
|
+
}
|
|
2461
|
+
/** Stores one trace record with its category list, byte size and step annotations; the profile retention window expires the heavy trace bytes while the metadata and annotations survive. */
|
|
2462
|
+
async settracerecord(trace) {
|
|
2463
|
+
const records = (await this.adapter.get("tracerecords") ?? []).filter((item) => item.id !== trace.id);
|
|
2464
|
+
const retention = (await this.getsettings())?.profileretention;
|
|
2465
|
+
const { traces } = expireprofilerecords({ heaps: [], profiles: [], traces: [trace, ...records], retention, now: Date.now() });
|
|
2466
|
+
await this.adapter.set("tracerecords", traces);
|
|
2467
|
+
}
|
|
2468
|
+
/** Returns every stored trace record, newest first. */
|
|
2469
|
+
async gettracerecords() {
|
|
2470
|
+
return await this.adapter.get("tracerecords") ?? [];
|
|
2471
|
+
}
|
|
2472
|
+
/** Returns the trace records filtered by run and applied categories. */
|
|
2473
|
+
async listtraces(filter) {
|
|
2474
|
+
const records = await this.gettracerecords();
|
|
2475
|
+
return records.filter((trace) => (filter.runid === void 0 || trace.runid === filter.runid) && (filter.categories === void 0 || filter.categories.every((category) => trace.categories.includes(category))));
|
|
2476
|
+
}
|
|
2477
|
+
/** Stores the exported file content of one trace beside its record; the retention window drops the file bytes of expired traces while the record survives. */
|
|
2478
|
+
async settracefile(traceid, content) {
|
|
2479
|
+
const records = (await this.adapter.get("tracefiles") ?? []).filter((item) => item.traceid !== traceid);
|
|
2480
|
+
const trace = (await this.gettracerecords()).find((item) => item.id === traceid);
|
|
2481
|
+
const retention = (await this.getsettings())?.profileretention;
|
|
2482
|
+
const kept = retention === void 0 || trace === void 0 || Date.now() - trace.endedat <= retention ? [{ traceid, content, savedat: Date.now() }, ...records] : records;
|
|
2483
|
+
await this.adapter.set("tracefiles", kept);
|
|
2484
|
+
}
|
|
2485
|
+
/** Returns the exported file content of one trace, or undefined when the retention window dropped the bytes. */
|
|
2486
|
+
async gettracefile(traceid) {
|
|
2487
|
+
const records = await this.adapter.get("tracefiles") ?? [];
|
|
2488
|
+
return records.find((item) => item.traceid === traceid)?.content;
|
|
2489
|
+
}
|
|
2490
|
+
/** Stores one source map reference of a run with its script url, map url and parsed state. */
|
|
2491
|
+
async setsourcemapref(ref) {
|
|
2492
|
+
const records = (await this.adapter.get("sourcemaprefs") ?? []).filter((item) => item.id !== ref.id);
|
|
2493
|
+
await this.adapter.set("sourcemaprefs", [ref, ...records]);
|
|
2494
|
+
}
|
|
2495
|
+
/** Returns every stored source map reference, newest first. */
|
|
2496
|
+
async getsourcemaps() {
|
|
2497
|
+
return await this.adapter.get("sourcemaprefs") ?? [];
|
|
2498
|
+
}
|
|
2499
|
+
/** Stores one source map capture consent decision per origin, replacing the previous decision of its id. */
|
|
2500
|
+
async setsourcemapconsent(consent) {
|
|
2501
|
+
const records = (await this.adapter.get("sourcemapconsents") ?? []).filter((item) => item.id !== consent.id);
|
|
2502
|
+
await this.adapter.set("sourcemapconsents", [consent, ...records]);
|
|
2503
|
+
}
|
|
2504
|
+
/** Returns every source map capture consent decision, newest first. */
|
|
2505
|
+
async getsourcemapconsents() {
|
|
2506
|
+
return await this.adapter.get("sourcemapconsents") ?? [];
|
|
2507
|
+
}
|
|
2508
|
+
/** Revokes every approved source map consent of one origin so the next capture needs a new reviewed prompt. */
|
|
2509
|
+
async revokesourcemapconsents(origin, at) {
|
|
2510
|
+
const records = await this.getsourcemapconsents();
|
|
2511
|
+
let revoked = 0;
|
|
2512
|
+
const updated = records.map((consent) => {
|
|
2513
|
+
if (consent.origin !== origin || consent.revokedat !== void 0) return consent;
|
|
2514
|
+
revoked += 1;
|
|
2515
|
+
return { ...consent, revokedat: at };
|
|
2516
|
+
});
|
|
2517
|
+
await this.adapter.set("sourcemapconsents", updated);
|
|
2518
|
+
return revoked;
|
|
2519
|
+
}
|
|
2167
2520
|
};
|
|
2168
2521
|
function mediakindof(record2) {
|
|
2169
2522
|
if ("pages" in record2) return "pdf";
|
|
@@ -3110,9 +3463,9 @@ function polldecision(input) {
|
|
|
3110
3463
|
}
|
|
3111
3464
|
|
|
3112
3465
|
// policy.ts
|
|
3113
|
-
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript"]);
|
|
3466
|
+
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps"]);
|
|
3114
3467
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr"]);
|
|
3115
|
-
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp"]);
|
|
3468
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace"]);
|
|
3116
3469
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
3117
3470
|
var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
|
|
3118
3471
|
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement", "captureframe", "shotcanvas"]);
|
|
@@ -3130,6 +3483,7 @@ var netwatchactions = /* @__PURE__ */ new Set(["watchrequests", "readheaders", "
|
|
|
3130
3483
|
var controlactions = /* @__PURE__ */ new Set(["blockrequest", "mockresponse", "rewriteheaders", "setcookies", "readcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles"]);
|
|
3131
3484
|
var debugactions = /* @__PURE__ */ new Set(["watchconsole", "watcherrors", "watchtasks"]);
|
|
3132
3485
|
var cdpactions = /* @__PURE__ */ new Set(["attachcdp", "detachcdp", "cdpcmd", "watchcdp", "setbreakpoint", "stepcode", "watchexpr", "overridescript"]);
|
|
3486
|
+
var profileractions = /* @__PURE__ */ new Set(["measureflow", "heapshot", "trackmemory", "profilecpu", "watchshifts", "traceload", "annotatetrace", "replaytrace", "capturesourcemaps"]);
|
|
3133
3487
|
var credentialheaders = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2", "set-cookie", "api-key", "x-api-key", "x-auth-token", "x-session-token", "proxy-authorization"]);
|
|
3134
3488
|
var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
|
|
3135
3489
|
var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
|
|
@@ -3154,8 +3508,11 @@ function isdebugkind(kind) {
|
|
|
3154
3508
|
function iscdpkind(kind) {
|
|
3155
3509
|
return cdpactions.has(kind);
|
|
3156
3510
|
}
|
|
3511
|
+
function isprofilekind(kind) {
|
|
3512
|
+
return profileractions.has(kind);
|
|
3513
|
+
}
|
|
3157
3514
|
function observationmodeof(kind) {
|
|
3158
|
-
if (watchactions.has(kind) || debugactions.has(kind) || cdpactions.has(kind) && kind === "watchcdp" || kind === "waitquiet") return "watching";
|
|
3515
|
+
if (watchactions.has(kind) || debugactions.has(kind) || profileractions.has(kind) && kind !== "heapshot" && kind !== "replaytrace" && kind !== "annotatetrace" && kind !== "capturesourcemaps" && kind !== "profilecpu" || cdpactions.has(kind) && kind === "watchcdp" || kind === "waitquiet") return "watching";
|
|
3159
3516
|
if (kind === "diffsnapshots") return "diffing";
|
|
3160
3517
|
return "passive";
|
|
3161
3518
|
}
|
|
@@ -4384,6 +4741,31 @@ function debuggerconsentcovers(origin, domains, grants) {
|
|
|
4384
4741
|
if (grants.some((grant) => grant.origin === origin && grant.revokedat !== void 0)) return { allowed: false, reason: `The debugger consent on ${origin} was revoked; approve a new prompt before the devtools protocol runs again.` };
|
|
4385
4742
|
return { allowed: false, reason: `The devtools protocol on ${origin} needs the reviewed debugger consent for ${needed.join(", ")} first; approve the prompt with the domain allowlist shown in the review panel.` };
|
|
4386
4743
|
}
|
|
4744
|
+
function targetgate(input) {
|
|
4745
|
+
const base = debuggate(input.session, input.tabid, input.origin, input.now);
|
|
4746
|
+
if (!base.allowed) return base;
|
|
4747
|
+
for (const target of input.targets) {
|
|
4748
|
+
if (target.kind === "page") continue;
|
|
4749
|
+
const origincheckresult = origincheck(input.session, target.url);
|
|
4750
|
+
if (!origincheckresult.allowed) return { allowed: false, reason: `The ${target.kind} target ${target.url} stays outside the granted origins; profiling refuses to attach.` };
|
|
4751
|
+
}
|
|
4752
|
+
if (input.grants === void 0) return { allowed: true };
|
|
4753
|
+
const consent = debuggerconsentcovers(input.origin, [], input.grants);
|
|
4754
|
+
if (!consent.allowed) return { allowed: false, reason: `The profiling step on ${input.origin} needs the reviewed debugger grant of the origin first; approve the prompt with the profiling derivation shown in the review panel.` };
|
|
4755
|
+
return { allowed: true };
|
|
4756
|
+
}
|
|
4757
|
+
function sourcemapconsentcovers(origin, consents) {
|
|
4758
|
+
const covering = consents.find((consent) => consent.origin === origin && consent.approved === true && consent.revokedat === void 0);
|
|
4759
|
+
if (covering) return { allowed: true };
|
|
4760
|
+
if (consents.some((consent) => consent.origin === origin && consent.revokedat !== void 0)) return { allowed: false, reason: `The source map capture consent on ${origin} was revoked; approve a new prompt before another map file is fetched.` };
|
|
4761
|
+
return { allowed: false, reason: `The source map capture on ${origin} needs the reviewed per origin consent first; approve the prompt shown in the review panel.` };
|
|
4762
|
+
}
|
|
4763
|
+
function profileretentionwindow(settings) {
|
|
4764
|
+
return settings?.profileretention;
|
|
4765
|
+
}
|
|
4766
|
+
function traceceilingof(settings) {
|
|
4767
|
+
return settings?.traceceiling;
|
|
4768
|
+
}
|
|
4387
4769
|
function validatebreakpointcondition(condition) {
|
|
4388
4770
|
const expression = condition.trim();
|
|
4389
4771
|
if (expression.length === 0) return { allowed: false, reason: "The breakpoint condition must not be empty." };
|
|
@@ -4479,6 +4861,66 @@ function validatecdpgrammar(step, options) {
|
|
|
4479
4861
|
}
|
|
4480
4862
|
return { allowed: true };
|
|
4481
4863
|
}
|
|
4864
|
+
function validateprofilegrammar(step, options) {
|
|
4865
|
+
const kind = step.kind;
|
|
4866
|
+
if (kind === "measureflow") {
|
|
4867
|
+
if (flowspecof(options.flow) === void 0) return { allowed: false, reason: `The flow measurement needs a reviewed flow spec with its mark prefix, step window and metric list of the reviewed metric set: navigation, paint, lcp, fid, interaction, blocking.` };
|
|
4868
|
+
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
4869
|
+
if (typeof watch.window !== "number" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: "The flow measurement needs a reviewed watch window of zero or more milliseconds." };
|
|
4870
|
+
const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === "number" ? options.wait : void 0);
|
|
4871
|
+
if (!budgetcheck.allowed) return budgetcheck;
|
|
4872
|
+
return { allowed: true };
|
|
4873
|
+
}
|
|
4874
|
+
if (kind === "heapshot") {
|
|
4875
|
+
const heap = options.heap && typeof options.heap === "object" && !Array.isArray(options.heap) ? options.heap : {};
|
|
4876
|
+
if (heap.interval !== void 0 && (typeof heap.interval !== "number" || !Number.isFinite(heap.interval) || heap.interval < 0)) return { allowed: false, reason: "The reviewed heap snapshot interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling." };
|
|
4877
|
+
return { allowed: true };
|
|
4878
|
+
}
|
|
4879
|
+
if (kind === "trackmemory") {
|
|
4880
|
+
const growth = options.growth && typeof options.growth === "object" && !Array.isArray(options.growth) ? options.growth : void 0;
|
|
4881
|
+
if (!growth || typeof growth.slope !== "number" || !Number.isFinite(growth.slope) || growth.slope < 0) return { allowed: false, reason: "Memory growth tracking needs the reviewed slope in bytes per millisecond before any sample is flagged." };
|
|
4882
|
+
if (growth.interval !== void 0 && (typeof growth.interval !== "number" || !Number.isFinite(growth.interval) || growth.interval < 0)) return { allowed: false, reason: "The reviewed sampling interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling." };
|
|
4883
|
+
return { allowed: true };
|
|
4884
|
+
}
|
|
4885
|
+
if (kind === "profilecpu") {
|
|
4886
|
+
const profile = options.profile && typeof options.profile === "object" && !Array.isArray(options.profile) ? options.profile : void 0;
|
|
4887
|
+
if (!profile || typeof profile.duration !== "number" || !Number.isFinite(profile.duration) || profile.duration < 0) return { allowed: false, reason: "The cpu profile needs a reviewed duration of zero or more milliseconds." };
|
|
4888
|
+
const budgetcheck = debugwaitbudgetallowed(profile.duration, typeof options.wait === "number" ? options.wait : void 0);
|
|
4889
|
+
if (!budgetcheck.allowed) return budgetcheck;
|
|
4890
|
+
return { allowed: true };
|
|
4891
|
+
}
|
|
4892
|
+
if (kind === "watchshifts") {
|
|
4893
|
+
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
4894
|
+
if (typeof watch.window !== "number" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: "The layout shift watch needs a reviewed observation window of zero or more milliseconds; the window stays a user choice with no code ceiling." };
|
|
4895
|
+
if (options.threshold !== void 0 && (typeof options.threshold !== "number" || !Number.isFinite(options.threshold) || options.threshold < 0)) return { allowed: false, reason: "The reviewed shift score threshold must be zero or a positive number." };
|
|
4896
|
+
const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === "number" ? options.wait : void 0);
|
|
4897
|
+
if (!budgetcheck.allowed) return budgetcheck;
|
|
4898
|
+
return { allowed: true };
|
|
4899
|
+
}
|
|
4900
|
+
if (kind === "traceload") {
|
|
4901
|
+
const trace = options.trace && typeof options.trace === "object" && !Array.isArray(options.trace) ? options.trace : void 0;
|
|
4902
|
+
if (!trace || !Array.isArray(trace.categories) || trace.categories.length === 0 || !trace.categories.every((category) => typeof category === "string" && tracecategories.includes(category))) return { allowed: false, reason: `The trace record needs a non-empty reviewed category list of the reviewed category grammar: ${tracecategories.join(", ")}.` };
|
|
4903
|
+
if (typeof trace.window !== "number" || !Number.isFinite(trace.window) || trace.window < 0) return { allowed: false, reason: "The trace record needs a reviewed window of zero or more milliseconds and stops at the reviewed window end." };
|
|
4904
|
+
if (trace.exporttarget !== void 0 && trace.exporttarget !== "memory" && trace.exporttarget !== "download") return { allowed: false, reason: "The trace export target must be memory or download." };
|
|
4905
|
+
const budgetcheck = debugwaitbudgetallowed(trace.window, typeof options.wait === "number" ? options.wait : void 0);
|
|
4906
|
+
if (!budgetcheck.allowed) return budgetcheck;
|
|
4907
|
+
return { allowed: true };
|
|
4908
|
+
}
|
|
4909
|
+
if (kind === "annotatetrace" || kind === "replaytrace") {
|
|
4910
|
+
const trace = options.trace && typeof options.trace === "object" && !Array.isArray(options.trace) ? options.trace : void 0;
|
|
4911
|
+
if (!trace || typeof trace.traceid !== "string" || !trace.traceid.trim()) return { allowed: false, reason: `The ${kind === "annotatetrace" ? "trace annotation" : "trace replay"} needs the stored trace id of a recorded trace.` };
|
|
4912
|
+
if (kind === "replaytrace") return { allowed: true };
|
|
4913
|
+
if (!Array.isArray(options.annotations) || options.annotations.length === 0 || !options.annotations.every((annotation) => annotationof(annotation) !== void 0)) return { allowed: false, reason: "Exported traces carry their step annotations: every annotation needs a step id, a label and an optional offset from the trace start." };
|
|
4914
|
+
return { allowed: true };
|
|
4915
|
+
}
|
|
4916
|
+
if (kind === "capturesourcemaps") {
|
|
4917
|
+
if (options.scripts !== void 0) {
|
|
4918
|
+
if (!Array.isArray(options.scripts) || options.scripts.length === 0 || !options.scripts.every((url) => typeof url === "string" && ishttpsurl(url))) return { allowed: false, reason: "The source map capture scripts must be a non-empty list of reviewed HTTPS urls." };
|
|
4919
|
+
}
|
|
4920
|
+
return { allowed: true };
|
|
4921
|
+
}
|
|
4922
|
+
return { allowed: true };
|
|
4923
|
+
}
|
|
4482
4924
|
function planallowlist(steps) {
|
|
4483
4925
|
const attach = steps.find((step) => step.kind === "attachcdp");
|
|
4484
4926
|
if (!attach) return void 0;
|
|
@@ -4906,6 +5348,10 @@ function validatestep(step, origin) {
|
|
|
4906
5348
|
const cdpcheck = validatecdpgrammar(step, options);
|
|
4907
5349
|
if (!cdpcheck.allowed) return cdpcheck;
|
|
4908
5350
|
}
|
|
5351
|
+
if (isprofilekind(step.kind)) {
|
|
5352
|
+
const profilecheck = validateprofilegrammar(step, options);
|
|
5353
|
+
if (!profilecheck.allowed) return profilecheck;
|
|
5354
|
+
}
|
|
4909
5355
|
if (step.kind === "tabcreate") {
|
|
4910
5356
|
if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
|
|
4911
5357
|
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
|
|
@@ -5039,15 +5485,39 @@ function canexecute(input) {
|
|
|
5039
5485
|
if (input.step.kind === "setbreakpoint") {
|
|
5040
5486
|
const breakpoint = breakpointinputof(cdpoptions.breakpoint);
|
|
5041
5487
|
if (breakpoint) {
|
|
5042
|
-
const
|
|
5043
|
-
if (!
|
|
5488
|
+
const targetgate2 = origincheck(input.session, breakpoint.url);
|
|
5489
|
+
if (!targetgate2.allowed) return targetgate2;
|
|
5044
5490
|
}
|
|
5045
5491
|
}
|
|
5046
5492
|
if (input.step.kind === "overridescript") {
|
|
5047
5493
|
const override = overrideinputof(cdpoptions.override);
|
|
5048
5494
|
if (override) {
|
|
5049
|
-
const
|
|
5050
|
-
if (!
|
|
5495
|
+
const targetgate2 = origincheck(input.session, override.urlpattern);
|
|
5496
|
+
if (!targetgate2.allowed) return targetgate2;
|
|
5497
|
+
}
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
if (isprofilekind(input.step.kind)) {
|
|
5501
|
+
let profileoptions = {};
|
|
5502
|
+
try {
|
|
5503
|
+
profileoptions = parseoptions(input.step);
|
|
5504
|
+
} catch {
|
|
5505
|
+
profileoptions = {};
|
|
5506
|
+
}
|
|
5507
|
+
const targets = [
|
|
5508
|
+
...attachtargetof(profileoptions.target) !== void 0 ? [attachtargetof(profileoptions.target)] : [],
|
|
5509
|
+
...Array.isArray(profileoptions.attachtargets) ? profileoptions.attachtargets.flatMap((target) => {
|
|
5510
|
+
const parsed = attachtargetof(target);
|
|
5511
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
5512
|
+
}) : []
|
|
5513
|
+
];
|
|
5514
|
+
const targetgatecheck = targetgate({ session: input.session, tabid: input.tabid, origin: input.origin, targets, grants: void 0, now });
|
|
5515
|
+
if (!targetgatecheck.allowed) return targetgatecheck;
|
|
5516
|
+
if (input.step.kind === "capturesourcemaps") {
|
|
5517
|
+
for (const url of Array.isArray(profileoptions.scripts) ? profileoptions.scripts : []) {
|
|
5518
|
+
if (typeof url !== "string") continue;
|
|
5519
|
+
const scriptgate = origincheck(input.session, url);
|
|
5520
|
+
if (!scriptgate.allowed) return scriptgate;
|
|
5051
5521
|
}
|
|
5052
5522
|
}
|
|
5053
5523
|
}
|
|
@@ -5096,8 +5566,8 @@ function canexecute(input) {
|
|
|
5096
5566
|
}
|
|
5097
5567
|
const target = controltarget(input.step);
|
|
5098
5568
|
if (target !== void 0) {
|
|
5099
|
-
const
|
|
5100
|
-
if (!
|
|
5569
|
+
const targetgate2 = origincheck(input.session, target);
|
|
5570
|
+
if (!targetgate2.allowed) return targetgate2;
|
|
5101
5571
|
}
|
|
5102
5572
|
}
|
|
5103
5573
|
if (input.step.kind === "extractapi") {
|
|
@@ -5134,7 +5604,7 @@ function canexecute(input) {
|
|
|
5134
5604
|
}
|
|
5135
5605
|
|
|
5136
5606
|
// version.ts
|
|
5137
|
-
var packageversion = "1.1.
|
|
5607
|
+
var packageversion = "1.1.47";
|
|
5138
5608
|
|
|
5139
5609
|
// types.ts
|
|
5140
5610
|
var protocolversion = packageversion;
|
|
@@ -5253,6 +5723,59 @@ function parseproposal(value, origin, grants) {
|
|
|
5253
5723
|
if (!allowlistcovers(planallowlist2, method)) throw new Error(`The raw command ${method} stays outside the enabled domain allowlist of the plan attach.`);
|
|
5254
5724
|
}
|
|
5255
5725
|
}
|
|
5726
|
+
if (isprofilekind(step.kind)) {
|
|
5727
|
+
const granted = covered.some((pattern) => {
|
|
5728
|
+
try {
|
|
5729
|
+
return new URL(origin).origin === new URL(pattern).origin;
|
|
5730
|
+
} catch {
|
|
5731
|
+
return false;
|
|
5732
|
+
}
|
|
5733
|
+
});
|
|
5734
|
+
if (!granted) throw new Error(`The ${step.kind} step of ${origin} targets an origin outside the grants.`);
|
|
5735
|
+
let profileoptions = {};
|
|
5736
|
+
try {
|
|
5737
|
+
profileoptions = parseoptions(step);
|
|
5738
|
+
} catch {
|
|
5739
|
+
profileoptions = {};
|
|
5740
|
+
}
|
|
5741
|
+
const targets = [
|
|
5742
|
+
...attachtargetof(profileoptions.target) !== void 0 ? [attachtargetof(profileoptions.target)] : [],
|
|
5743
|
+
...Array.isArray(profileoptions.attachtargets) ? profileoptions.attachtargets.flatMap((target2) => {
|
|
5744
|
+
const parsed = attachtargetof(target2);
|
|
5745
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
5746
|
+
}) : []
|
|
5747
|
+
];
|
|
5748
|
+
for (const target2 of targets) {
|
|
5749
|
+
if (target2.kind === "page") continue;
|
|
5750
|
+
const targetgranted = covered.some((pattern) => {
|
|
5751
|
+
try {
|
|
5752
|
+
return new URL(target2.url).origin === new URL(pattern).origin;
|
|
5753
|
+
} catch {
|
|
5754
|
+
return false;
|
|
5755
|
+
}
|
|
5756
|
+
});
|
|
5757
|
+
if (!targetgranted) throw new Error(`The ${target2.kind} target ${target2.url} of the ${step.kind} step stays outside the granted origins.`);
|
|
5758
|
+
}
|
|
5759
|
+
if (step.kind === "traceload") {
|
|
5760
|
+
const trace = profileoptions.trace && typeof profileoptions.trace === "object" && !Array.isArray(profileoptions.trace) ? profileoptions.trace : void 0;
|
|
5761
|
+
const categories = trace !== void 0 && Array.isArray(trace.categories) ? trace.categories : [];
|
|
5762
|
+
if (categories.some((category) => typeof category !== "string" || !tracecategories.includes(category))) throw new Error(`Trace categories outside the reviewed list are refused: ${tracecategories.join(", ")}.`);
|
|
5763
|
+
}
|
|
5764
|
+
if (step.kind === "capturesourcemaps") {
|
|
5765
|
+
for (const url of Array.isArray(profileoptions.scripts) ? profileoptions.scripts : []) {
|
|
5766
|
+
if (typeof url !== "string") continue;
|
|
5767
|
+
const scriptgranted = covered.some((pattern) => {
|
|
5768
|
+
try {
|
|
5769
|
+
return new URL(url).origin === new URL(pattern).origin;
|
|
5770
|
+
} catch {
|
|
5771
|
+
return false;
|
|
5772
|
+
}
|
|
5773
|
+
});
|
|
5774
|
+
if (!scriptgranted) throw new Error(`The source map capture of ${url} targets an origin outside the grants.`);
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
if (step.kind === "annotatetrace" && (!Array.isArray(profileoptions.annotations) || profileoptions.annotations.length === 0 || !profileoptions.annotations.every((annotation) => annotationof(annotation) !== void 0))) throw new Error("Trace annotation steps without reviewed step annotations are refused.");
|
|
5778
|
+
}
|
|
5256
5779
|
const evaluation = validatestep(step, origin);
|
|
5257
5780
|
if (!evaluation.allowed) throw new Error(evaluation.reason);
|
|
5258
5781
|
const target = outboundtarget(step);
|
|
@@ -5327,7 +5850,7 @@ function requestbody(input) {
|
|
|
5327
5850
|
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
5328
5851
|
}
|
|
5329
5852
|
function outcomeresponse(input) {
|
|
5330
|
-
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {} });
|
|
5853
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {} });
|
|
5331
5854
|
}
|
|
5332
5855
|
function mapresponse(input) {
|
|
5333
5856
|
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
|
|
@@ -5457,8 +5980,18 @@ function cdpreport(input) {
|
|
|
5457
5980
|
});
|
|
5458
5981
|
return { version: protocolversion, sessions: input.sessions, commands: input.commands, events: input.events, breakpoints: input.breakpoints, pauses: input.pauses, watches: input.watches, overrides, grants };
|
|
5459
5982
|
}
|
|
5983
|
+
function profilereport(input) {
|
|
5984
|
+
const consents = input.consents.map((consent) => {
|
|
5985
|
+
const { prompt, ...metadata } = consent;
|
|
5986
|
+
void prompt;
|
|
5987
|
+
return metadata;
|
|
5988
|
+
});
|
|
5989
|
+
return { version: protocolversion, flows: input.flows, heaps: input.heaps, samples: input.samples, trends: input.trends, profiles: input.profiles, shifts: input.shifts, traces: input.traces, sourcemaps: input.sourcemaps, consents };
|
|
5990
|
+
}
|
|
5460
5991
|
export {
|
|
5461
5992
|
allowlistcovers,
|
|
5993
|
+
annotatetrace,
|
|
5994
|
+
annotationof,
|
|
5462
5995
|
annotationplanof,
|
|
5463
5996
|
apientries,
|
|
5464
5997
|
apikeyconsentgranted,
|
|
@@ -5467,6 +6000,7 @@ export {
|
|
|
5467
6000
|
argkind,
|
|
5468
6001
|
assetentries,
|
|
5469
6002
|
attachcdpsession,
|
|
6003
|
+
attachtargetof,
|
|
5470
6004
|
attachtimeline,
|
|
5471
6005
|
authconsentgranted,
|
|
5472
6006
|
authorizeurl,
|
|
@@ -5498,6 +6032,7 @@ export {
|
|
|
5498
6032
|
capturepause,
|
|
5499
6033
|
captureregion,
|
|
5500
6034
|
capturereport,
|
|
6035
|
+
capturesourcemaps,
|
|
5501
6036
|
capturestates,
|
|
5502
6037
|
capturestitched,
|
|
5503
6038
|
capturetargets,
|
|
@@ -5523,6 +6058,7 @@ export {
|
|
|
5523
6058
|
cookiegate,
|
|
5524
6059
|
cookierecordof,
|
|
5525
6060
|
correlationid,
|
|
6061
|
+
cpusnap,
|
|
5526
6062
|
croprect,
|
|
5527
6063
|
crossesviewport,
|
|
5528
6064
|
cursorfrom,
|
|
@@ -5540,6 +6076,7 @@ export {
|
|
|
5540
6076
|
errorreportresponse,
|
|
5541
6077
|
eventresponse,
|
|
5542
6078
|
exchangesreport,
|
|
6079
|
+
expireprofilerecords,
|
|
5543
6080
|
extractionreport,
|
|
5544
6081
|
extractvalues,
|
|
5545
6082
|
failureclass,
|
|
@@ -5549,14 +6086,20 @@ export {
|
|
|
5549
6086
|
filterexchanges,
|
|
5550
6087
|
finishrecording,
|
|
5551
6088
|
fixedheadermatch,
|
|
6089
|
+
flowmetricnames,
|
|
6090
|
+
flowspecof,
|
|
5552
6091
|
formpayloadof,
|
|
5553
6092
|
formreportresponse,
|
|
5554
6093
|
frameinterval,
|
|
5555
6094
|
generatedvalueallowed,
|
|
5556
6095
|
graphqlopenvelope,
|
|
5557
6096
|
graphqlrequestof,
|
|
6097
|
+
growsampleof,
|
|
6098
|
+
growthtrend,
|
|
5558
6099
|
headerfilterof,
|
|
5559
6100
|
headeruleof,
|
|
6101
|
+
heapintervalallowed,
|
|
6102
|
+
heapsnap,
|
|
5560
6103
|
heldkeysreport,
|
|
5561
6104
|
hostpattern,
|
|
5562
6105
|
htmlqueriesof,
|
|
@@ -5569,6 +6112,7 @@ export {
|
|
|
5569
6112
|
isdebugkind,
|
|
5570
6113
|
isformkind,
|
|
5571
6114
|
isnetwatchkind,
|
|
6115
|
+
isprofilekind,
|
|
5572
6116
|
issocketkind,
|
|
5573
6117
|
iswatchkind,
|
|
5574
6118
|
jsonpathrulesof,
|
|
@@ -5579,8 +6123,10 @@ export {
|
|
|
5579
6123
|
loglevels,
|
|
5580
6124
|
longtaskcapture,
|
|
5581
6125
|
mapresponse,
|
|
6126
|
+
mapurlof,
|
|
5582
6127
|
matchmessage,
|
|
5583
6128
|
matchurlpattern,
|
|
6129
|
+
measure,
|
|
5584
6130
|
mediaentries,
|
|
5585
6131
|
mediakinds,
|
|
5586
6132
|
mediareport,
|
|
@@ -5630,6 +6176,9 @@ export {
|
|
|
5630
6176
|
pollurl,
|
|
5631
6177
|
privatemime,
|
|
5632
6178
|
profilegrantgranted,
|
|
6179
|
+
profilereport,
|
|
6180
|
+
profileretentionwindow,
|
|
6181
|
+
profilerkinds,
|
|
5633
6182
|
protocolversion,
|
|
5634
6183
|
provenancereport,
|
|
5635
6184
|
proxygate,
|
|
@@ -5651,6 +6200,7 @@ export {
|
|
|
5651
6200
|
redactedcookies,
|
|
5652
6201
|
regionsteps,
|
|
5653
6202
|
rejectioncapture,
|
|
6203
|
+
replaytrace,
|
|
5654
6204
|
replayurl,
|
|
5655
6205
|
requestbody,
|
|
5656
6206
|
resolutionverdict,
|
|
@@ -5659,6 +6209,7 @@ export {
|
|
|
5659
6209
|
retryafterof,
|
|
5660
6210
|
revertrule,
|
|
5661
6211
|
revocationruleof,
|
|
6212
|
+
rewritesourcelocation,
|
|
5662
6213
|
rotatelogs,
|
|
5663
6214
|
rotationruleof,
|
|
5664
6215
|
safetyresponse,
|
|
@@ -5671,9 +6222,11 @@ export {
|
|
|
5671
6222
|
serializearg,
|
|
5672
6223
|
serializecdpcommand,
|
|
5673
6224
|
sessionmemory,
|
|
6225
|
+
shiftentryof,
|
|
5674
6226
|
signalsreport,
|
|
5675
6227
|
socketgate,
|
|
5676
6228
|
socketkinds,
|
|
6229
|
+
sourcemapconsentcovers,
|
|
5677
6230
|
spamdetect,
|
|
5678
6231
|
spamruleof,
|
|
5679
6232
|
sserequestheaders,
|
|
@@ -5681,11 +6234,13 @@ export {
|
|
|
5681
6234
|
stackgate,
|
|
5682
6235
|
statusclassof,
|
|
5683
6236
|
stepmodeof,
|
|
6237
|
+
stepwindows,
|
|
5684
6238
|
streamsummaries,
|
|
5685
6239
|
streamwindowof,
|
|
5686
6240
|
submitreviewgranted,
|
|
5687
6241
|
subscriptionoptionsof,
|
|
5688
6242
|
tabreportresponse,
|
|
6243
|
+
targetgate,
|
|
5689
6244
|
teardowncdpsession,
|
|
5690
6245
|
teardownplanof,
|
|
5691
6246
|
templateurl,
|
|
@@ -5698,6 +6253,10 @@ export {
|
|
|
5698
6253
|
timelineretentionwindow,
|
|
5699
6254
|
timelinesources,
|
|
5700
6255
|
tokenrequest,
|
|
6256
|
+
tracecategories,
|
|
6257
|
+
traceceilingof,
|
|
6258
|
+
tracestart,
|
|
6259
|
+
tracetofile,
|
|
5701
6260
|
trailreport,
|
|
5702
6261
|
transformgrammar,
|
|
5703
6262
|
unwrapgraphql,
|