@wenathlan/extension 1.1.44 → 1.1.46
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 +6 -4
- package/dist/cdpbus.d.ts +104 -0
- package/dist/cdpbus.d.ts.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +937 -6
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +75 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +39 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +63 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/runtimeline.d.ts +122 -0
- package/dist/runtimeline.d.ts.map +1 -0
- package/dist/types.d.ts +271 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1252 -9
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +439 -7
- package/extension/dist/pagebridge.js.map +4 -4
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +18 -3
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +281 -3
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +6 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnOEjO8Z0PDgQyfvawGcaO2j+o0GLCFTLNj7TkYC/Avo9l2NenMRq7gp90Nfd7E9MViv/OMcCKSYZ5unv12QPRtv31C+a5UQWDFAOP/cH5mwMd6hsayElrSoW8ta+FwFqmr9dIFkn7cQEU3YhZr4Gcbs+ycUHOxVgDA4NBKB0rQ6e9VW5LvTw0isRYUrqM+M72vKxHk9zUIYYn/LGPvottKBYi2GLr0PHSeC2UE+Shmq7vcFIXj6hDjvD4kLJ5sKoUllEcZ1TPuBcnHUQ9ndKA5iktXDQOIJCUJmi7a0YJ2PGg7fvpYfT9k0ai/qZ+pIoRfoOEwE01bPoDn7NjeYnNQIDAQAB",
|
|
4
4
|
"name": "Devthink",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.46",
|
|
6
6
|
"description": "A consent-first bridge for reviewed browser-agent tasks.",
|
|
7
7
|
"permissions": [
|
|
8
8
|
"activeTab",
|
|
@@ -1,9 +1,128 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
(() => {
|
|
3
|
+
// cdpbus.ts
|
|
4
|
+
function breakpointinputof(value) {
|
|
5
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
6
|
+
const entry = value;
|
|
7
|
+
const url = typeof entry.url === "string" && entry.url.trim() ? entry.url.trim() : void 0;
|
|
8
|
+
const line = typeof entry.line === "number" && Number.isInteger(entry.line) && entry.line >= 0 ? entry.line : void 0;
|
|
9
|
+
if (url === void 0 || line === void 0) return void 0;
|
|
10
|
+
const column = typeof entry.column === "number" && Number.isInteger(entry.column) && entry.column >= 0 ? entry.column : void 0;
|
|
11
|
+
const condition = typeof entry.condition === "string" && entry.condition.trim() ? entry.condition.trim() : void 0;
|
|
12
|
+
return { url, line, ...column !== void 0 ? { column } : {}, ...condition !== void 0 ? { condition } : {} };
|
|
13
|
+
}
|
|
14
|
+
function stepmodeof(value) {
|
|
15
|
+
const modes = ["stepover", "stepinto", "stepout", "resume"];
|
|
16
|
+
return typeof value === "string" && modes.includes(value) ? value : void 0;
|
|
17
|
+
}
|
|
18
|
+
function watchexpressionof(value) {
|
|
19
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
20
|
+
const entry = value;
|
|
21
|
+
const expression = typeof entry.expression === "string" && entry.expression.trim() ? entry.expression.trim() : void 0;
|
|
22
|
+
if (expression === void 0) return void 0;
|
|
23
|
+
const scope = typeof entry.scope === "string" && entry.scope.trim() ? entry.scope.trim() : "topframe";
|
|
24
|
+
return { expression, scope };
|
|
25
|
+
}
|
|
26
|
+
function overrideinputof(value) {
|
|
27
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
28
|
+
const entry = value;
|
|
29
|
+
const urlpattern = typeof entry.urlpattern === "string" && entry.urlpattern.trim() ? entry.urlpattern.trim() : void 0;
|
|
30
|
+
const source = typeof entry.source === "string" ? entry.source : void 0;
|
|
31
|
+
if (urlpattern === void 0 || source === void 0 || source.trim().length === 0) return void 0;
|
|
32
|
+
return { urlpattern, source };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// runtimeline.ts
|
|
36
|
+
var loglevels = ["error", "warn", "info", "log", "debug", "trace"];
|
|
37
|
+
function levelrank(level) {
|
|
38
|
+
return loglevels.indexOf(level);
|
|
39
|
+
}
|
|
40
|
+
function redactconsoletext(text, patterns) {
|
|
41
|
+
let redacted = text;
|
|
42
|
+
for (const pattern of patterns) {
|
|
43
|
+
if (!pattern) continue;
|
|
44
|
+
while (redacted.includes(pattern)) redacted = redacted.replace(pattern, "[redacted]");
|
|
45
|
+
}
|
|
46
|
+
return redacted;
|
|
47
|
+
}
|
|
48
|
+
function argkind(value) {
|
|
49
|
+
if (value === null) return "null";
|
|
50
|
+
if (Array.isArray(value)) return "array";
|
|
51
|
+
if (value instanceof Error) return "error";
|
|
52
|
+
switch (typeof value) {
|
|
53
|
+
case "string":
|
|
54
|
+
return "string";
|
|
55
|
+
case "number":
|
|
56
|
+
return "number";
|
|
57
|
+
case "boolean":
|
|
58
|
+
return "boolean";
|
|
59
|
+
case "bigint":
|
|
60
|
+
return "bigint";
|
|
61
|
+
case "symbol":
|
|
62
|
+
return "symbol";
|
|
63
|
+
case "function":
|
|
64
|
+
return "function";
|
|
65
|
+
case "undefined":
|
|
66
|
+
return "undefined";
|
|
67
|
+
default:
|
|
68
|
+
return "object";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function serializearg(value, depth) {
|
|
72
|
+
const render = (item, remaining) => {
|
|
73
|
+
if (item instanceof Error) return `${item.name}: ${item.message}`;
|
|
74
|
+
if (typeof item === "string") return item;
|
|
75
|
+
if (typeof item === "function") return `[function ${item.name || "anonymous"}]`;
|
|
76
|
+
if (typeof item === "bigint") return `${item}n`;
|
|
77
|
+
if (typeof item === "symbol") return item.toString();
|
|
78
|
+
if (item === null || item === void 0 || typeof item !== "object") return String(item);
|
|
79
|
+
if (remaining <= 0) {
|
|
80
|
+
const tag = Array.isArray(item) ? "Array" : item.constructor?.name ?? "Object";
|
|
81
|
+
return `[${tag}]`;
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(item)) return `[${item.map((entry) => render(entry, remaining - 1)).join(", ")}]`;
|
|
84
|
+
const record = item;
|
|
85
|
+
return `{${Object.keys(record).map((key) => `${key}: ${render(record[key], remaining - 1)}`).join(", ")}}`;
|
|
86
|
+
};
|
|
87
|
+
return render(value, Math.max(0, depth));
|
|
88
|
+
}
|
|
89
|
+
function consolecapture(input) {
|
|
90
|
+
const parts = input.args.map((arg) => serializearg(arg, input.depth));
|
|
91
|
+
return { level: input.level, text: redactconsoletext(parts.join(" "), input.redact), argkinds: input.args.map((arg) => argkind(arg)), repeat: 1 };
|
|
92
|
+
}
|
|
93
|
+
function stackframes(stacktext) {
|
|
94
|
+
const frames = [];
|
|
95
|
+
for (const row of stacktext.split("\n")) {
|
|
96
|
+
const trimmed = row.trim();
|
|
97
|
+
if (!trimmed.startsWith("at ")) continue;
|
|
98
|
+
const body = trimmed.slice(3).trim();
|
|
99
|
+
const location2 = body.match(/\(([^()]*:\d+:\d+)\)$/) ?? body.match(/^(.*:\d+:\d+)$/);
|
|
100
|
+
const located = location2?.[1];
|
|
101
|
+
if (!located) continue;
|
|
102
|
+
const segments = located.split(":");
|
|
103
|
+
const column = Number.parseInt(segments.pop() ?? "", 10);
|
|
104
|
+
const lineno = Number.parseInt(segments.pop() ?? "", 10);
|
|
105
|
+
const url = segments.join(":");
|
|
106
|
+
if (!Number.isFinite(lineno) || lineno < 0) continue;
|
|
107
|
+
const name = body.endsWith(`(${located})`) ? body.slice(0, body.length - located.length - 2).trim() : "";
|
|
108
|
+
frames.push({ ...name ? { functionname: name } : {}, url, line: lineno, ...Number.isFinite(column) ? { column } : {} });
|
|
109
|
+
}
|
|
110
|
+
return frames;
|
|
111
|
+
}
|
|
112
|
+
function errorcapture(input) {
|
|
113
|
+
return { message: redactconsoletext(input.message, input.redact), frames: input.stacktext !== void 0 ? stackframes(input.stacktext) : [], sourceurl: input.sourceurl, line: input.line };
|
|
114
|
+
}
|
|
115
|
+
function rejectioncapture(input) {
|
|
116
|
+
return { reason: redactconsoletext(input.reason, input.redact), frames: input.stacktext !== void 0 ? stackframes(input.stacktext) : [] };
|
|
117
|
+
}
|
|
118
|
+
function longtaskcapture(input) {
|
|
119
|
+
return input.entries.filter((entry) => entry.duration >= input.threshold).map((entry) => ({ duration: Math.round(entry.duration), starttime: Math.round(entry.starttime), attributions: [...entry.attributions] }));
|
|
120
|
+
}
|
|
121
|
+
|
|
3
122
|
// policy.ts
|
|
4
|
-
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"]);
|
|
5
|
-
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"]);
|
|
6
|
-
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"]);
|
|
123
|
+
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"]);
|
|
124
|
+
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"]);
|
|
125
|
+
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"]);
|
|
7
126
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
8
127
|
function parseoptions(step) {
|
|
9
128
|
if (step.options === void 0) return {};
|
|
@@ -2358,6 +2477,315 @@
|
|
|
2358
2477
|
}
|
|
2359
2478
|
}
|
|
2360
2479
|
|
|
2480
|
+
// extension/pagedebug.ts
|
|
2481
|
+
var harnesskey = "__devthinkcdp";
|
|
2482
|
+
function readharness() {
|
|
2483
|
+
return globalThis[harnesskey];
|
|
2484
|
+
}
|
|
2485
|
+
function writeharness(harness) {
|
|
2486
|
+
if (harness === void 0) delete globalThis[harnesskey];
|
|
2487
|
+
else globalThis[harnesskey] = harness;
|
|
2488
|
+
}
|
|
2489
|
+
var instrumentedmethods = /* @__PURE__ */ new Set(["Runtime.evaluate", "Log.enable", "Debugger.enable", "DOM.enable", "Network.enable", "Page.enable", "DOM.getSnapshot", "Page.getNavigationHistory"]);
|
|
2490
|
+
function cdpstepoptions(step) {
|
|
2491
|
+
let options = {};
|
|
2492
|
+
try {
|
|
2493
|
+
options = parseoptions(step);
|
|
2494
|
+
} catch {
|
|
2495
|
+
options = {};
|
|
2496
|
+
}
|
|
2497
|
+
const teardown = options.teardown && typeof options.teardown === "object" && !Array.isArray(options.teardown) && Array.isArray(options.teardown.revertsteps) ? { revertsteps: options.teardown.revertsteps.filter((item) => typeof item === "string"), resumepolicy: String(options.teardown.resumepolicy ?? "ask") } : void 0;
|
|
2498
|
+
const command = options.command && typeof options.command === "object" && !Array.isArray(options.command) ? options.command : void 0;
|
|
2499
|
+
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
2500
|
+
const breakpoint = breakpointinputof(options.breakpoint);
|
|
2501
|
+
const expression = watchexpressionof(options.expression);
|
|
2502
|
+
const override = overrideinputof(options.override);
|
|
2503
|
+
return {
|
|
2504
|
+
domains: Array.isArray(options.domains) ? options.domains.filter((domain) => typeof domain === "string") : [],
|
|
2505
|
+
...teardown !== void 0 ? { teardown } : {},
|
|
2506
|
+
...command !== void 0 && typeof command.method === "string" ? { command: { method: command.method, ...command.params && typeof command.params === "object" && !Array.isArray(command.params) ? { params: command.params } : {}, ...typeof command.resultpath === "string" ? { resultpath: command.resultpath } : {} } } : {},
|
|
2507
|
+
events: Array.isArray(options.events) ? options.events.flatMap((rule) => {
|
|
2508
|
+
const parsed = rule && typeof rule === "object" && !Array.isArray(rule) ? rule : void 0;
|
|
2509
|
+
if (!parsed || typeof parsed.domain !== "string" || typeof parsed.event !== "string") return [];
|
|
2510
|
+
return [{ domain: parsed.domain, event: parsed.event, ...typeof parsed.match === "string" ? { match: parsed.match } : {} }];
|
|
2511
|
+
}) : [],
|
|
2512
|
+
watchwindow: typeof watch.window === "number" && Number.isFinite(watch.window) && watch.window >= 0 ? watch.window : 0,
|
|
2513
|
+
...breakpoint !== void 0 ? { breakpoint } : {},
|
|
2514
|
+
...options.mode !== void 0 && stepmodeof(options.mode) !== void 0 ? { mode: options.mode } : {},
|
|
2515
|
+
...expression !== void 0 ? { expression } : {},
|
|
2516
|
+
...override !== void 0 ? { override } : {}
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
function domstate() {
|
|
2520
|
+
return { url: location.href, title: document.title, nodes: document.querySelectorAll("*").length, forms: document.forms.length };
|
|
2521
|
+
}
|
|
2522
|
+
async function runcdpstep(step) {
|
|
2523
|
+
const options = cdpstepoptions(step);
|
|
2524
|
+
if (step.kind === "attachcdp") {
|
|
2525
|
+
const existing = readharness();
|
|
2526
|
+
if (existing) {
|
|
2527
|
+
for (const detach of existing.hooks) detach();
|
|
2528
|
+
}
|
|
2529
|
+
const harness = { domains: options.domains, breakpoints: [], overrides: [], events: [], hooks: [] };
|
|
2530
|
+
if (options.domains.includes("Log") || options.domains.includes("Runtime")) {
|
|
2531
|
+
for (const level of loglevels) {
|
|
2532
|
+
const original = console[level];
|
|
2533
|
+
const hooked = (...args) => {
|
|
2534
|
+
try {
|
|
2535
|
+
original.apply(console, args);
|
|
2536
|
+
} catch {
|
|
2537
|
+
}
|
|
2538
|
+
harness.events.push({ domain: "Log", event: "entryAdded", payload: args.map((arg) => serializearg(arg, 2)).join(" "), at: Date.now() });
|
|
2539
|
+
};
|
|
2540
|
+
console[level] = hooked;
|
|
2541
|
+
harness.hooks.push(() => {
|
|
2542
|
+
console[level] = original;
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
writeharness(harness);
|
|
2547
|
+
return { ok: true, summary: `Attached the instrumented devtools harness with the reviewed domains ${options.domains.join(", ")} enabled.`, details: { attached: true, domains: [...harness.domains], derivation: "The chrome devtools protocol needs the debugger permission, which the manifest gate forbids; the session runs through the page-instrumented harness injected by the scripting api." } };
|
|
2548
|
+
}
|
|
2549
|
+
if (step.kind === "detachcdp") {
|
|
2550
|
+
const harness = readharness();
|
|
2551
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2552
|
+
for (const detach of harness.hooks) detach();
|
|
2553
|
+
const reverted = { breakpoints: harness.breakpoints.length, overrides: harness.overrides.length };
|
|
2554
|
+
writeharness(void 0);
|
|
2555
|
+
return { ok: true, summary: `Detached the instrumented devtools harness cleanly after reverting ${reverted.breakpoints} breakpoint${reverted.breakpoints === 1 ? "" : "s"} and ${reverted.overrides} override${reverted.overrides === 1 ? "" : "s"}.`, details: { detached: true, ...reverted } };
|
|
2556
|
+
}
|
|
2557
|
+
if (step.kind === "cdpcmd") {
|
|
2558
|
+
const harness = readharness();
|
|
2559
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2560
|
+
const method = options.command?.method ?? "";
|
|
2561
|
+
const params = options.command?.params ?? {};
|
|
2562
|
+
if (!instrumentedmethods.has(method)) return { ok: false, summary: `The reviewed command ${method} reports the uninstrumented error class: the page harness implements ${[...instrumentedmethods].join(", ")} only.`, details: { method, errorclass: "uninstrumented" } };
|
|
2563
|
+
const started = Date.now();
|
|
2564
|
+
try {
|
|
2565
|
+
if (method === "Runtime.evaluate") {
|
|
2566
|
+
const expression = typeof params.expression === "string" ? params.expression : "";
|
|
2567
|
+
const probeurl = typeof params.url === "string" ? params.url : "inline";
|
|
2568
|
+
const scope = params.scope && typeof params.scope === "object" && !Array.isArray(params.scope) ? params.scope : {};
|
|
2569
|
+
const override = harness.overrides.find((spec) => overridematch(spec.urlpattern, probeurl));
|
|
2570
|
+
const source = override !== void 0 && overridematch(override.urlpattern, probeurl) ? override.source : expression;
|
|
2571
|
+
const value = new Function(...Object.keys(scope), `"use strict"; return (${source});`)(...Object.values(scope));
|
|
2572
|
+
let tripped;
|
|
2573
|
+
for (const breakpoint of harness.breakpoints) {
|
|
2574
|
+
if (breakpoint.url !== probeurl) continue;
|
|
2575
|
+
const conditionok = breakpoint.condition === void 0 ? true : Boolean(new Function(...Object.keys(scope), `"use strict"; return (${breakpoint.condition});`)(...Object.values(scope)));
|
|
2576
|
+
if (!conditionok) continue;
|
|
2577
|
+
breakpoint.hits += 1;
|
|
2578
|
+
tripped = { reason: "breakpoint", hitbreakpoint: breakpoint.id, frames: stackframes(new Error().stack ?? ""), scope, cursor: breakpoint.line, lines: Math.max(1, source.split("\n").length) };
|
|
2579
|
+
harness.paused = tripped;
|
|
2580
|
+
break;
|
|
2581
|
+
}
|
|
2582
|
+
const serialized = serializearg(value, 3);
|
|
2583
|
+
harness.events.push({ domain: "Runtime", event: "executionContextDestroyed", payload: serialized.slice(0, 200), at: Date.now() });
|
|
2584
|
+
return { ok: true, summary: `The reviewed command ${method} returned in ${Date.now() - started} milliseconds${tripped !== void 0 ? " and paused the run on the reviewed breakpoint" : ""}.`, details: { method, duration: Date.now() - started, result: { value: serialized }, ...tripped !== void 0 ? { paused: { reason: tripped.reason, hitbreakpoint: tripped.hitbreakpoint, frames: tripped.frames } } : {} } };
|
|
2585
|
+
}
|
|
2586
|
+
if (method === "DOM.getSnapshot") {
|
|
2587
|
+
const state = domstate();
|
|
2588
|
+
return { ok: true, summary: `The reviewed command ${method} returned the dom snapshot of ${state.nodes} nodes in ${Date.now() - started} milliseconds.`, details: { method, duration: Date.now() - started, result: state } };
|
|
2589
|
+
}
|
|
2590
|
+
if (method === "Page.getNavigationHistory") {
|
|
2591
|
+
const state = domstate();
|
|
2592
|
+
return { ok: true, summary: `The reviewed command ${method} returned the page navigation history in ${Date.now() - started} milliseconds.`, details: { method, duration: Date.now() - started, result: { url: state.url, title: state.title } } };
|
|
2593
|
+
}
|
|
2594
|
+
return { ok: true, summary: `The reviewed command ${method} enabled its domain through the instrumented harness in ${Date.now() - started} milliseconds.`, details: { method, duration: Date.now() - started, result: {} } };
|
|
2595
|
+
} catch (error) {
|
|
2596
|
+
return { ok: false, summary: `The reviewed command ${method} failed with the evaluationerror class: ${error instanceof Error ? error.message : String(error)}.`, details: { method, duration: Date.now() - started, errorclass: "evaluationerror" } };
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
if (step.kind === "watchcdp") {
|
|
2600
|
+
const harness = readharness();
|
|
2601
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2602
|
+
const started = Date.now();
|
|
2603
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
2604
|
+
if (harness.domains.includes("Page") && navigation !== void 0 && navigation.loadEventStart > 0) harness.events.push({ domain: "Page", event: "loadEventFired", payload: location.href, at: started });
|
|
2605
|
+
await wait4(options.watchwindow);
|
|
2606
|
+
const observed = harness.events.filter((event) => event.at >= started);
|
|
2607
|
+
return { ok: true, summary: `Observed ${observed.length} domain event${observed.length === 1 ? "" : "s"} for the reviewed window of ${options.watchwindow} milliseconds.`, details: { events: observed, watchwindow: options.watchwindow, derivation: "Domain events derive from the instrumented console hooks and the page performance navigation buffer because no debugger permission exists in the manifest." } };
|
|
2608
|
+
}
|
|
2609
|
+
if (step.kind === "setbreakpoint") {
|
|
2610
|
+
const harness = readharness();
|
|
2611
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2612
|
+
if (!options.breakpoint) return { ok: false, summary: "The breakpoint input is absent." };
|
|
2613
|
+
const id = `bp-${options.breakpoint.url}-${options.breakpoint.line}-${options.breakpoint.column ?? 0}`;
|
|
2614
|
+
const registered = { id, ...options.breakpoint, hits: 0 };
|
|
2615
|
+
harness.breakpoints.push(registered);
|
|
2616
|
+
return { ok: true, summary: `Registered the reviewed breakpoint at ${options.breakpoint.url}:${options.breakpoint.line}${options.breakpoint.condition !== void 0 ? ` under the condition ${options.breakpoint.condition}` : ""}.`, details: { breakpoint: registered } };
|
|
2617
|
+
}
|
|
2618
|
+
if (step.kind === "stepcode") {
|
|
2619
|
+
const harness = readharness();
|
|
2620
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2621
|
+
const mode = stepmodeof(options.mode);
|
|
2622
|
+
if (mode === void 0) return { ok: false, summary: "The step code mode is absent." };
|
|
2623
|
+
if (harness.paused === void 0) return { ok: false, summary: "No paused instrumented probe exists to step through; pause on a reviewed breakpoint first." };
|
|
2624
|
+
if (mode === "resume" || mode === "stepout") {
|
|
2625
|
+
const reason = harness.paused.reason;
|
|
2626
|
+
const frames = harness.paused.frames;
|
|
2627
|
+
delete harness.paused;
|
|
2628
|
+
return { ok: true, summary: `The ${mode} mode ${mode === "resume" ? "resumed" : "stepped out of"} the paused probe after ${frames.length} call frame${frames.length === 1 ? "" : "s"}.`, details: { mode, paused: false, reason } };
|
|
2629
|
+
}
|
|
2630
|
+
harness.paused.cursor += 1;
|
|
2631
|
+
const state = domstate();
|
|
2632
|
+
return { ok: true, summary: `The ${mode} mode advanced to line ${harness.paused.cursor} of the paused probe and captured the pause state with ${harness.paused.frames.length} call frame${harness.paused.frames.length === 1 ? "" : "s"} and the dom state.`, details: { mode, paused: true, pausestate: { reason: harness.paused.reason, ...harness.paused.hitbreakpoint !== void 0 ? { hitbreakpoint: harness.paused.hitbreakpoint } : {}, frames: harness.paused.frames, cursor: harness.paused.cursor, dom: state } } };
|
|
2633
|
+
}
|
|
2634
|
+
if (step.kind === "watchexpr") {
|
|
2635
|
+
const harness = readharness();
|
|
2636
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2637
|
+
if (!options.expression) return { ok: false, summary: "The watch expression input is absent." };
|
|
2638
|
+
if (harness.paused === void 0) return { ok: false, summary: "No paused instrumented probe exists to evaluate the watch expression in; pause on a reviewed breakpoint first." };
|
|
2639
|
+
try {
|
|
2640
|
+
const value = new Function(...Object.keys(harness.paused.scope), `"use strict"; return (${options.expression.expression});`)(...Object.values(harness.paused.scope));
|
|
2641
|
+
return { ok: true, summary: `Evaluated the reviewed watch expression at the pause in the ${options.expression.scope} scope.`, details: { expression: options.expression.expression, scope: options.expression.scope, value: serializearg(value, 3) } };
|
|
2642
|
+
} catch (error) {
|
|
2643
|
+
return { ok: false, summary: `The reviewed watch expression failed with the evaluationerror class: ${error instanceof Error ? error.message : String(error)}.`, details: { errorclass: "evaluationerror" } };
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
if (step.kind === "overridescript") {
|
|
2647
|
+
const harness = readharness();
|
|
2648
|
+
if (!harness) return { ok: false, summary: "No instrumented devtools harness is attached to this page." };
|
|
2649
|
+
if (!options.override) return { ok: false, summary: "The script override input is absent." };
|
|
2650
|
+
const id = `ov-${options.override.urlpattern}`;
|
|
2651
|
+
harness.overrides = harness.overrides.filter((spec) => spec.id !== id);
|
|
2652
|
+
harness.overrides.push({ id, urlpattern: options.override.urlpattern, source: options.override.source });
|
|
2653
|
+
try {
|
|
2654
|
+
new Function(options.override.source)();
|
|
2655
|
+
return { ok: true, summary: `Applied the reviewed script fixture for ${options.override.urlpattern} on the current document and on later instrumented evaluations of the pattern.`, details: { override: { id, urlpattern: options.override.urlpattern, applied: true } } };
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
return { ok: false, summary: `The reviewed script fixture failed with the evaluationerror class: ${error instanceof Error ? error.message : String(error)}.`, details: { errorclass: "evaluationerror" } };
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
return { ok: false, summary: "The devtools step is not part of the instrumented family." };
|
|
2661
|
+
}
|
|
2662
|
+
function overridematch(urlpattern, url) {
|
|
2663
|
+
const patternmatch = /^(https:\/\/[^/]+|inline)(\/.*)?$/.exec(urlpattern);
|
|
2664
|
+
const urlmatch = /^(https:\/\/[^/]+|inline)(\/.*)?$/.exec(url);
|
|
2665
|
+
if (!patternmatch || !urlmatch) return false;
|
|
2666
|
+
if (patternmatch[1] !== urlmatch[1]) return false;
|
|
2667
|
+
const patternpath = (patternmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
|
|
2668
|
+
const urlpath = (urlmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
|
|
2669
|
+
const walk = (patternindex, urlindex) => {
|
|
2670
|
+
if (patternindex >= patternpath.length) return urlindex >= urlpath.length;
|
|
2671
|
+
const segment = patternpath[patternindex];
|
|
2672
|
+
if (segment === "**") return walk(patternindex + 1, urlindex) || urlindex < urlpath.length && walk(patternindex, urlindex + 1);
|
|
2673
|
+
if (urlindex >= urlpath.length) return false;
|
|
2674
|
+
if (segment !== "*" && segment !== urlpath[urlindex]) return false;
|
|
2675
|
+
return walk(patternindex + 1, urlindex + 1);
|
|
2676
|
+
};
|
|
2677
|
+
return walk(0, 0);
|
|
2678
|
+
}
|
|
2679
|
+
function debugwatchoptions(step) {
|
|
2680
|
+
let options = {};
|
|
2681
|
+
try {
|
|
2682
|
+
options = parseoptions(step);
|
|
2683
|
+
} catch {
|
|
2684
|
+
options = {};
|
|
2685
|
+
}
|
|
2686
|
+
const watch = options.watch && typeof options.watch === "object" && !Array.isArray(options.watch) ? options.watch : {};
|
|
2687
|
+
const spam = options.spam && typeof options.spam === "object" && !Array.isArray(options.spam) ? options.spam : void 0;
|
|
2688
|
+
const rotation = options.rotation && typeof options.rotation === "object" && !Array.isArray(options.rotation) ? options.rotation : void 0;
|
|
2689
|
+
return {
|
|
2690
|
+
window: typeof watch.window === "number" && Number.isFinite(watch.window) && watch.window >= 0 ? watch.window : 0,
|
|
2691
|
+
...typeof options.level === "string" && loglevels.includes(options.level) ? { level: options.level } : {},
|
|
2692
|
+
depth: typeof options.depth === "number" && Number.isInteger(options.depth) && options.depth >= 1 ? options.depth : 2,
|
|
2693
|
+
redact: Array.isArray(options.redact) ? options.redact.filter((pattern) => typeof pattern === "string" && pattern.length > 0) : [],
|
|
2694
|
+
...spam && typeof spam.pattern === "string" && typeof spam.windowsize === "number" && typeof spam.collapse === "number" ? { spam: { pattern: spam.pattern, windowsize: spam.windowsize, collapse: spam.collapse } } : {},
|
|
2695
|
+
...rotation && typeof rotation.maxentries === "number" && typeof rotation.overflowtarget === "string" ? { rotation: { maxentries: rotation.maxentries, overflowtarget: rotation.overflowtarget } } : {},
|
|
2696
|
+
threshold: typeof options.threshold === "number" && Number.isFinite(options.threshold) && options.threshold >= 0 ? options.threshold : 0
|
|
2697
|
+
};
|
|
2698
|
+
}
|
|
2699
|
+
function wait4(milliseconds) {
|
|
2700
|
+
return new Promise((resolve) => window.setTimeout(resolve, Math.max(0, milliseconds)));
|
|
2701
|
+
}
|
|
2702
|
+
async function rundebugwatch(step) {
|
|
2703
|
+
const options = debugwatchoptions(step);
|
|
2704
|
+
if (options.window <= 0) return { ok: false, summary: "The reviewed debug watch window is absent." };
|
|
2705
|
+
const started = Date.now();
|
|
2706
|
+
const entries = [];
|
|
2707
|
+
const consoleentries = [];
|
|
2708
|
+
const errors = [];
|
|
2709
|
+
const rejections = [];
|
|
2710
|
+
const resources = [];
|
|
2711
|
+
const longtasks = [];
|
|
2712
|
+
const floor = options.level !== void 0 ? levelrank(options.level) : void 0;
|
|
2713
|
+
const capture = (level, source, message, at) => {
|
|
2714
|
+
if (floor !== void 0 && levelrank(level) > floor) return;
|
|
2715
|
+
entries.push({ stepid: step.id, time: at, level, source, message });
|
|
2716
|
+
};
|
|
2717
|
+
const hooks = [];
|
|
2718
|
+
if (step.kind === "watchconsole") {
|
|
2719
|
+
for (const level of loglevels) {
|
|
2720
|
+
const original = console[level];
|
|
2721
|
+
const hooked = (...args) => {
|
|
2722
|
+
try {
|
|
2723
|
+
original.apply(console, args);
|
|
2724
|
+
} catch {
|
|
2725
|
+
}
|
|
2726
|
+
const entry = consolecapture({ level, args, depth: options.depth, redact: options.redact });
|
|
2727
|
+
if (floor === void 0 || levelrank(level) <= floor) consoleentries.push(entry);
|
|
2728
|
+
capture(level, "console", entry.text, Date.now());
|
|
2729
|
+
};
|
|
2730
|
+
console[level] = hooked;
|
|
2731
|
+
hooks.push(() => {
|
|
2732
|
+
console[level] = original;
|
|
2733
|
+
});
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
if (step.kind === "watcherrors") {
|
|
2737
|
+
const onerror = (event) => {
|
|
2738
|
+
const record = errorcapture({ message: event.message, sourceurl: event.filename, line: event.lineno, ...event.error instanceof Error ? { stacktext: event.error.stack } : {}, redact: options.redact });
|
|
2739
|
+
errors.push({ ...record, stepid: step.id, at: Date.now() });
|
|
2740
|
+
capture("error", "error", record.message, Date.now());
|
|
2741
|
+
};
|
|
2742
|
+
const onrejection = (event) => {
|
|
2743
|
+
const reason = event.reason instanceof Error ? `${event.reason.name}: ${event.reason.message}` : String(event.reason);
|
|
2744
|
+
const record = rejectioncapture({ reason, ...event.reason instanceof Error ? { stacktext: event.reason.stack } : {}, redact: options.redact });
|
|
2745
|
+
rejections.push({ ...record, stepid: step.id, at: Date.now() });
|
|
2746
|
+
capture("error", "rejection", record.reason, Date.now());
|
|
2747
|
+
};
|
|
2748
|
+
const onresource = (event) => {
|
|
2749
|
+
const target = event.target;
|
|
2750
|
+
if (!(target instanceof Element)) return;
|
|
2751
|
+
const element = target.tagName.toLowerCase() + (target.id ? `#${target.id}` : "");
|
|
2752
|
+
const sourceurl = target instanceof HTMLImageElement || target instanceof HTMLScriptElement ? target.src ?? "" : target instanceof HTMLLinkElement ? target.href ?? "" : "";
|
|
2753
|
+
const message = `Failed to load ${element}${sourceurl ? ` from ${sourceurl}` : ""}.`;
|
|
2754
|
+
resources.push({ message, element, sourceurl });
|
|
2755
|
+
capture("error", "resource", message, Date.now());
|
|
2756
|
+
};
|
|
2757
|
+
window.addEventListener("error", onerror, true);
|
|
2758
|
+
window.addEventListener("unhandledrejection", onrejection, true);
|
|
2759
|
+
window.addEventListener("error", onresource, true);
|
|
2760
|
+
hooks.push(() => {
|
|
2761
|
+
window.removeEventListener("error", onerror, true);
|
|
2762
|
+
window.removeEventListener("unhandledrejection", onrejection, true);
|
|
2763
|
+
window.removeEventListener("error", onresource, true);
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
if (step.kind === "watchtasks") {
|
|
2767
|
+
const observer = new PerformanceObserver((list) => {
|
|
2768
|
+
for (const entry of list.getEntries()) {
|
|
2769
|
+
const detail = entry;
|
|
2770
|
+
const attributions = (detail.attribution ?? []).map((container) => String(container.name ?? "")).filter((name) => name.length > 0);
|
|
2771
|
+
longtasks.push({ stepid: step.id, duration: Math.round(detail.duration), starttime: Math.round(detail.startTime), attributions, at: Date.now() });
|
|
2772
|
+
}
|
|
2773
|
+
});
|
|
2774
|
+
observer.observe({ entryTypes: ["longtask"] });
|
|
2775
|
+
hooks.push(() => observer.disconnect());
|
|
2776
|
+
}
|
|
2777
|
+
await wait4(options.window);
|
|
2778
|
+
for (const detach of hooks) detach();
|
|
2779
|
+
if (step.kind === "watchtasks") {
|
|
2780
|
+
const filtered = longtaskcapture({ entries: longtasks, threshold: options.threshold });
|
|
2781
|
+
longtasks.length = 0;
|
|
2782
|
+
longtasks.push(...filtered.map((task) => ({ ...task, stepid: step.id, at: started })));
|
|
2783
|
+
for (const task of longtasks) capture("info", "longtask", `Long task of ${task.duration} milliseconds blocked the main thread${task.attributions.length > 0 ? ` (${task.attributions.join(", ")})` : ""}.`, task.at);
|
|
2784
|
+
}
|
|
2785
|
+
const summary = step.kind === "watchconsole" ? `Captured ${consoleentries.length} console call${consoleentries.length === 1 ? "" : "s"} at every level for the reviewed window of ${options.window} milliseconds.` : step.kind === "watcherrors" ? `Captured ${errors.length} error${errors.length === 1 ? "" : "s"}, ${rejections.length} rejection${rejections.length === 1 ? "" : "s"} and ${resources.length} resource failure${resources.length === 1 ? "" : "s"} for the reviewed window of ${options.window} milliseconds.` : `Captured ${longtasks.length} long task${longtasks.length === 1 ? "" : "s"} for the reviewed window of ${options.window} milliseconds.`;
|
|
2786
|
+
return { ok: true, summary, details: { entries, console: consoleentries, errors, rejections, resources, longtasks, watchwindow: options.window, depth: options.depth, derivation: "Console, error and task watching derives from page-injected listeners and the performance buffers through the scripting api; no debugger permission exists in the manifest." } };
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2361
2789
|
// extension/pageforms.ts
|
|
2362
2790
|
function matchfield(fields, match) {
|
|
2363
2791
|
const key = match.mode === "label" ? "label" : match.mode === "placeholder" ? "placeholder" : match.mode === "arialabel" ? "arialabel" : "name";
|
|
@@ -2786,7 +3214,7 @@
|
|
|
2786
3214
|
if (source === "reviewed") return typeof value === "string" && value.trim().length > 0;
|
|
2787
3215
|
return false;
|
|
2788
3216
|
}
|
|
2789
|
-
function
|
|
3217
|
+
function wait5(delay) {
|
|
2790
3218
|
return new Promise((resolve) => window.setTimeout(resolve, delay));
|
|
2791
3219
|
}
|
|
2792
3220
|
function pollfor2(predicate, description, timeout) {
|
|
@@ -2900,7 +3328,7 @@
|
|
|
2900
3328
|
for (const group of cardgroups(value)) {
|
|
2901
3329
|
element.value = group;
|
|
2902
3330
|
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2903
|
-
if (pause > 0) await
|
|
3331
|
+
if (pause > 0) await wait5(pause);
|
|
2904
3332
|
}
|
|
2905
3333
|
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2906
3334
|
filled.push({ label: String(match[key] ?? ""), masked: cardmask(value) });
|
|
@@ -3077,7 +3505,7 @@
|
|
|
3077
3505
|
if (step.kind === "paginateextract") {
|
|
3078
3506
|
const nextselector = typeof options.next === "string" ? options.next : "";
|
|
3079
3507
|
const pages = typeof options.pages === "number" && Number.isInteger(options.pages) && options.pages > 0 ? options.pages : 1;
|
|
3080
|
-
const
|
|
3508
|
+
const wait6 = typeof options.wait === "number" && Number.isFinite(options.wait) && options.wait > 0 ? options.wait : 0;
|
|
3081
3509
|
const cursor = typeof options.cursor === "number" && Number.isInteger(options.cursor) && options.cursor > 0 ? options.cursor : 0;
|
|
3082
3510
|
const grids = [];
|
|
3083
3511
|
let previous = [];
|
|
@@ -3093,7 +3521,7 @@
|
|
|
3093
3521
|
const control = root.querySelector(nextselector);
|
|
3094
3522
|
if (!control) break;
|
|
3095
3523
|
control.click();
|
|
3096
|
-
const deadline = Date.now() +
|
|
3524
|
+
const deadline = Date.now() + wait6;
|
|
3097
3525
|
let fresh = false;
|
|
3098
3526
|
while (!fresh && Date.now() < deadline) {
|
|
3099
3527
|
await new Promise((resolve) => window.setTimeout(resolve, Math.min(100, Math.max(16, deadline - Date.now()))));
|
|
@@ -3230,6 +3658,8 @@
|
|
|
3230
3658
|
var observationkinds = /* @__PURE__ */ new Set(["a11ytree", "readvisible", "readertree", "readoutline", "readselection", "readopengraph", "readlang", "detectlanguage", "listshadow", "listframes"]);
|
|
3231
3659
|
var detectionkinds = /* @__PURE__ */ new Set(["detectlists", "detecttables", "detectinfinitescroll", "detectvirtual", "detectlazy", "detectsticky", "detectscrolllock", "countpages", "classifypage", "fingerprintsection", "readscrollpos"]);
|
|
3232
3660
|
var watchstepkinds = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "waitquiet", "readjson", "diffsnapshots", "deriveselector"]);
|
|
3661
|
+
var debugstepkinds = /* @__PURE__ */ new Set(["watchconsole", "watcherrors", "watchtasks"]);
|
|
3662
|
+
var cdpstepkinds = /* @__PURE__ */ new Set(["attachcdp", "detachcdp", "cdpcmd", "watchcdp", "setbreakpoint", "stepcode", "watchexpr", "overridescript"]);
|
|
3233
3663
|
var navstepkinds = /* @__PURE__ */ new Set(["waitload", "waiturl", "followlink", "spanav", "spawait", "rewritequery", "setfragment", "stopnav", "prefetch", "preconnect", "printpdf"]);
|
|
3234
3664
|
var formkinds = /* @__PURE__ */ new Set(["fillform", "filllabel", "fillplaceholder", "detectfields", "generatevalues", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "asksubmit", "submitform", "consentpassword", "attachfile"]);
|
|
3235
3665
|
var wizardkinds = /* @__PURE__ */ new Set(["runwizard", "selectchain", "picktypeahead", "pickdate", "fillcard", "fillcode"]);
|
|
@@ -3295,6 +3725,8 @@
|
|
|
3295
3725
|
else if (observationkinds.has(step.kind)) result = runpageobservation(step, element, rootdocument);
|
|
3296
3726
|
else if (detectionkinds.has(step.kind)) result = runpagedetection(step, element, rootdocument);
|
|
3297
3727
|
else if (watchstepkinds.has(step.kind)) result = runpagewatch(step, element, rootdocument);
|
|
3728
|
+
else if (debugstepkinds.has(step.kind)) return await rundebugwatch(step);
|
|
3729
|
+
else if (cdpstepkinds.has(step.kind)) return await runcdpstep(step);
|
|
3298
3730
|
else if (mutatingkinds.has(step.kind)) result = runpageaction(step, element);
|
|
3299
3731
|
else {
|
|
3300
3732
|
if (!element) return { ok: false, summary: "Action target is no longer available." };
|