@descryy/runtime-browser 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/dist/browser-console-collector.d.ts +10 -18
- package/dist/browser-console-collector.d.ts.map +1 -1
- package/dist/browser-console-collector.js +24 -47
- package/dist/browser-console-collector.js.map +1 -1
- package/dist/browser-session.d.ts +46 -78
- package/dist/browser-session.d.ts.map +1 -1
- package/dist/browser-session.js +21 -41
- package/dist/browser-session.js.map +1 -1
- package/dist/collector-version.d.ts +3 -6
- package/dist/collector-version.d.ts.map +1 -1
- package/dist/collector-version.js +3 -6
- package/dist/collector-version.js.map +1 -1
- package/dist/dom-evidence.d.ts +3 -6
- package/dist/dom-evidence.d.ts.map +1 -1
- package/dist/dom-evidence.js +3 -6
- package/dist/dom-evidence.js.map +1 -1
- package/dist/frontend-initiator-capture.d.ts +29 -64
- package/dist/frontend-initiator-capture.d.ts.map +1 -1
- package/dist/frontend-initiator-capture.js +31 -67
- package/dist/frontend-initiator-capture.js.map +1 -1
- package/dist/network-correlation.d.ts +4 -7
- package/dist/network-correlation.d.ts.map +1 -1
- package/dist/network-correlation.js +4 -7
- package/dist/network-correlation.js.map +1 -1
- package/dist/script-url-mapping.d.ts +11 -22
- package/dist/script-url-mapping.d.ts.map +1 -1
- package/dist/script-url-mapping.js +18 -47
- package/dist/script-url-mapping.js.map +1 -1
- package/package.json +9 -4
package/LICENSE
ADDED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* §8
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `EvidenceSource: "browser-console"` bucket the contracts already name.
|
|
2
|
+
* §8 console evidence (level/message/stack/timestamp) plus page errors --
|
|
3
|
+
* uncaught JS exceptions via Playwright's `pageerror` event. Both use the
|
|
4
|
+
* `EvidenceSource: "browser-console"` bucket.
|
|
6
5
|
*
|
|
7
|
-
* Page-error stack text is preserved verbatim
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `
|
|
11
|
-
* (`stackCapture`/`sourceMapping`: unavailable), not silently produced as
|
|
12
|
-
* a lesser version. Doing that for real would need mapping the browser's
|
|
13
|
-
* `http://` script URLs back to on-disk files via the frontend's static
|
|
14
|
-
* file server root, which this collector has no way to know -- a real,
|
|
15
|
-
* separate feature, not built here.
|
|
6
|
+
* Page-error stack text is preserved verbatim (§9: preserve the original
|
|
7
|
+
* observation) but without a parser is not structurally parsed into
|
|
8
|
+
* `StackTrace` frames -- reflected honestly in `capabilities()`
|
|
9
|
+
* (`stackCapture`/`sourceMapping`: unavailable), not silently downgraded.
|
|
16
10
|
*/
|
|
17
11
|
import type { Collector } from "@descryy/runtime-contracts";
|
|
18
12
|
import type { StackTraceParser } from "@descryy/runtime-backend-observation";
|
|
@@ -21,11 +15,9 @@ export interface BrowserConsoleCollectorOptions {
|
|
|
21
15
|
readonly session: BrowserSession;
|
|
22
16
|
readonly service?: string;
|
|
23
17
|
/**
|
|
24
|
-
* Injected, never constructed here
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* actually watching. Omit it and page-error stacks are preserved as text
|
|
28
|
-
* exactly as before, with `capabilities()` saying so.
|
|
18
|
+
* Injected, never constructed here -- stays language-neutral like
|
|
19
|
+
* `LogCollector`. Omit it and stacks are preserved as text, with
|
|
20
|
+
* `capabilities()` saying so.
|
|
29
21
|
*/
|
|
30
22
|
readonly stackTraceParser?: StackTraceParser;
|
|
31
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-console-collector.d.ts","sourceRoot":"","sources":["../src/browser-console-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-console-collector.d.ts","sourceRoot":"","sources":["../src/browser-console-collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAqF,MAAM,4BAA4B,CAAC;AAG/I,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CAC9C;AAgDD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG,SAAS,CAgHhG"}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* §8
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `EvidenceSource: "browser-console"` bucket the contracts already name.
|
|
2
|
+
* §8 console evidence (level/message/stack/timestamp) plus page errors --
|
|
3
|
+
* uncaught JS exceptions via Playwright's `pageerror` event. Both use the
|
|
4
|
+
* `EvidenceSource: "browser-console"` bucket.
|
|
6
5
|
*
|
|
7
|
-
* Page-error stack text is preserved verbatim
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `
|
|
11
|
-
* (`stackCapture`/`sourceMapping`: unavailable), not silently produced as
|
|
12
|
-
* a lesser version. Doing that for real would need mapping the browser's
|
|
13
|
-
* `http://` script URLs back to on-disk files via the frontend's static
|
|
14
|
-
* file server root, which this collector has no way to know -- a real,
|
|
15
|
-
* separate feature, not built here.
|
|
6
|
+
* Page-error stack text is preserved verbatim (§9: preserve the original
|
|
7
|
+
* observation) but without a parser is not structurally parsed into
|
|
8
|
+
* `StackTrace` frames -- reflected honestly in `capabilities()`
|
|
9
|
+
* (`stackCapture`/`sourceMapping`: unavailable), not silently downgraded.
|
|
16
10
|
*/
|
|
17
11
|
import { primaryFrameLocation } from "@descryy/runtime-contracts";
|
|
18
12
|
import { extractCorrelationIds } from "@descryy/runtime-backend-observation";
|
|
@@ -43,15 +37,12 @@ const CAPABILITIES = {
|
|
|
43
37
|
externalServiceObservation: notThisCollectorsJob("external service observation"),
|
|
44
38
|
};
|
|
45
39
|
/**
|
|
46
|
-
* RT-023
|
|
47
|
-
*
|
|
48
|
-
* rewritten to on-disk paths.
|
|
40
|
+
* RT-023: with a parser injected and `resolveSourceRoot` present,
|
|
41
|
+
* page-error stacks are parsed and script URLs rewritten to on-disk paths.
|
|
49
42
|
*
|
|
50
|
-
* `sourceMapping` stays
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* the checkout in it (`declaredCwd` is named for exactly that). A script
|
|
54
|
-
* this execution did not serve — a CDN, an extension — is left as a URL.
|
|
43
|
+
* `sourceMapping` stays degraded, not available: the lookup proves the
|
|
44
|
+
* origin maps to a configured directory, not that the executed file came
|
|
45
|
+
* from that checkout. A script this execution didn't serve is left as URL.
|
|
55
46
|
*/
|
|
56
47
|
const CAPABILITIES_WITH_STACKS = {
|
|
57
48
|
...CAPABILITIES,
|
|
@@ -73,15 +64,11 @@ export function createBrowserConsoleCollector(options) {
|
|
|
73
64
|
/**
|
|
74
65
|
* In-flight `onPageError` handlers.
|
|
75
66
|
*
|
|
76
|
-
* Parsing
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* `stop()` is called at the end of every execution, which is precisely
|
|
82
|
-
* when a page's last error arrives, so this was not a rare window.
|
|
83
|
-
*
|
|
84
|
-
* `stop()` now drains this set before clearing `emit`.
|
|
67
|
+
* Parsing is async but Playwright's `pageerror` listener isn't, so
|
|
68
|
+
* `stop()` used to clear `emit` while a parse was still running --
|
|
69
|
+
* `emit?.()` on undefined is a silent no-op, dropping the page's last
|
|
70
|
+
* error every time (stop() runs right when it arrives). `stop()` now
|
|
71
|
+
* drains this set first.
|
|
85
72
|
*/
|
|
86
73
|
const inFlight = new Set();
|
|
87
74
|
function onConsole(msg) {
|
|
@@ -122,23 +109,18 @@ export function createBrowserConsoleCollector(options) {
|
|
|
122
109
|
eventType: "EXCEPTION",
|
|
123
110
|
payload: {
|
|
124
111
|
message: error.message,
|
|
125
|
-
//
|
|
126
|
-
// (plan §9: preserve the original observation).
|
|
112
|
+
// raw browser text, unchanged by the mapping (§9: preserve the original observation).
|
|
127
113
|
stack: rawStack,
|
|
128
114
|
browserSessionId: session.sessionId,
|
|
129
|
-
//
|
|
130
|
-
// mapped, one is a CDN" is a coverage statement, and collapsing
|
|
131
|
-
// it would imply the unmapped one simply was not there.
|
|
115
|
+
// per-URL outcomes, not a boolean -- collapsing would hide the partially-mapped case.
|
|
132
116
|
...(mapping !== null ? { scriptUrlMapping: mapping.outcomes } : {}),
|
|
133
117
|
},
|
|
134
118
|
traceId: null,
|
|
135
119
|
requestId: null,
|
|
136
120
|
correlationId: null,
|
|
137
121
|
graphNodeId: null,
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
// only because V8 reports index 0 — a coincidence, not a shared
|
|
141
|
-
// rule. The full chain is in stackTrace either way.
|
|
122
|
+
// backend-observation moved to primaryFrameIndex (RT-083); frames[0] agreement was
|
|
123
|
+
// coincidence (V8 reports index 0), not a shared rule. Full chain is in stackTrace either way.
|
|
142
124
|
sourceLocation: primaryFrameLocation(stackTrace),
|
|
143
125
|
stackTrace,
|
|
144
126
|
confidence: 1,
|
|
@@ -157,9 +139,7 @@ export function createBrowserConsoleCollector(options) {
|
|
|
157
139
|
}
|
|
158
140
|
emit = context.emit;
|
|
159
141
|
resolveSourceRoot = context.resolveSourceRoot;
|
|
160
|
-
//
|
|
161
|
-
// produce frames pointing at http:// locations nothing can open, and
|
|
162
|
-
// a mapper with no parser has nothing to map.
|
|
142
|
+
// both halves or neither: a parser without a mapper points at http:// nothing can open, and a mapper without a parser has nothing to map.
|
|
163
143
|
stacksParsed = options.stackTraceParser !== undefined && context.resolveSourceRoot !== undefined;
|
|
164
144
|
page.on("console", onConsole);
|
|
165
145
|
page.on("pageerror", onPageError);
|
|
@@ -169,11 +149,8 @@ export function createBrowserConsoleCollector(options) {
|
|
|
169
149
|
// Listeners off first, so nothing new joins the set while it drains.
|
|
170
150
|
page.off("console", onConsole);
|
|
171
151
|
page.off("pageerror", onPageError);
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
// `allSettled`: a handler that threw has already failed on its own
|
|
175
|
-
// terms, and stop() refusing to complete because of it would take the
|
|
176
|
-
// rest of the run's evidence down with it.
|
|
152
|
+
// drain then clear emit -- clearing first silently dropped the last page error.
|
|
153
|
+
// allSettled: a handler that threw already failed on its own terms and shouldn't block the rest.
|
|
177
154
|
await Promise.allSettled([...inFlight]);
|
|
178
155
|
emit = undefined;
|
|
179
156
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-console-collector.js","sourceRoot":"","sources":["../src/browser-console-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-console-collector.js","sourceRoot":"","sources":["../src/browser-console-collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAI7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAa3D,SAAS,oBAAoB,CAAC,IAAY;IACxC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,4EAA4E,IAAI,kCAAkC,EAAE,CAAC;AACrK,CAAC;AAED,MAAM,YAAY,GAA0B;IAC1C,cAAc,EAAE,oBAAoB,CAAC,gBAAgB,CAAC;IACtD,kBAAkB,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE;IAC/D,kBAAkB,EAAE,oBAAoB,CAAC,qBAAqB,CAAC;IAC/D,gBAAgB,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,gEAAgE,EAAE;IAC3H,gBAAgB,EAAE;QAChB,YAAY,EAAE,UAAU;QACxB,MAAM,EAAE,kHAAkH;KAC3H;IACD,aAAa,EAAE;QACb,YAAY,EAAE,aAAa;QAC3B,MAAM,EAAE,oGAAoG;KAC7G;IACD,YAAY,EAAE;QACZ,YAAY,EAAE,aAAa;QAC3B,MAAM,EAAE,6GAA6G;KACtH;IACD,gBAAgB,EAAE,oBAAoB,CAAC,+BAA+B,CAAC;IACvE,mBAAmB,EAAE,oBAAoB,CAAC,4BAA4B,CAAC;IACvE,0BAA0B,EAAE,oBAAoB,CAAC,8BAA8B,CAAC;CACjF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,wBAAwB,GAA0B;IACtD,GAAG,YAAY;IACf,aAAa,EAAE;QACb,YAAY,EAAE,UAAU;QACxB,MAAM,EACJ,4HAA4H;YAC5H,2HAA2H;YAC3H,6DAA6D;KAChE;IACD,YAAY,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE;CAC1D,CAAC;AAEF,MAAM,UAAU,6BAA6B,CAAC,OAAuC;IACnF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,IAAI,IAAwB,CAAC;IAC7B,IAAI,iBAAwD,CAAC;IAC7D,qGAAqG;IACrG,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB;;;;;;;;OAQG;IACH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE1C,SAAS,SAAS,CAAC,GAAmB;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,EAAE,CAAC;YACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,iBAAiB;YACzB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;YAChC,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,iBAAiB;YAC5B,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,gBAAgB,EAAE,OAAO,CAAC,SAAS,EAAE;YACnG,OAAO;YACP,SAAS;YACT,aAAa,EAAE,IAAI;YACnB,WAAW,EAAE,IAAI;YACjB,cAAc,EAAE,IAAI;YACpB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,CAAC;YACb,eAAe,EAAE,mBAAmB;YACpC,gBAAgB,EAAE,iBAAiB;SACpC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,WAAW,CAAC,KAAY;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,KAAK,IAAmB,EAAE;YACzC,IAAI,UAAU,GAAsB,IAAI,CAAC;YACzC,IAAI,OAAO,GAAgD,IAAI,CAAC;YAEhE,IAAI,YAAY,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBAChF,OAAO,GAAG,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;gBACzD,UAAU,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAClE,CAAC;YAED,IAAI,EAAE,CAAC;gBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,MAAM,EAAE,iBAAiB;gBACzB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;gBAChC,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,WAAW;gBACtB,OAAO,EAAE;oBACP,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,sFAAsF;oBACtF,KAAK,EAAE,QAAQ;oBACf,gBAAgB,EAAE,OAAO,CAAC,SAAS;oBACnC,sFAAsF;oBACtF,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpE;gBACD,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,aAAa,EAAE,IAAI;gBACnB,WAAW,EAAE,IAAI;gBACjB,mFAAmF;gBACnF,+FAA+F;gBAC/F,cAAc,EAAE,oBAAoB,CAAC,UAAU,CAAC;gBAChD,UAAU;gBACV,UAAU,EAAE,CAAC;gBACb,eAAe,EAAE,mBAAmB;gBACpC,gBAAgB,EAAE,iBAAiB;aACpC,CAAC,CAAC;QACL,CAAC,CAAC,EAAE,CAAC;QACL,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACL,WAAW,EAAE,mBAAmB,OAAO,CAAC,SAAS,EAAE;QAEnD,KAAK,CAAC,OAAyB;YAC7B,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACxB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,2DAA2D,EAAE,CAAC,CAAC;YACpH,CAAC;YACD,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YACpB,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAC9C,0IAA0I;YAC1I,YAAY,GAAG,OAAO,CAAC,gBAAgB,KAAK,SAAS,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,CAAC;YACjG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YAClC,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,KAAK,CAAC,IAAI;YACR,qEAAqE;YACrE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACnC,gFAAgF;YAChF,iGAAiG;YACjG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;YACxC,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;QAED,YAAY;YACV,OAAO,YAAY,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,YAAY,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,35 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* §7
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* isolation unit -- separate cookies/storage/cache per context) plus its
|
|
7
|
-
* one page, which is what plan §7's "isolated context/session · page
|
|
8
|
-
* creation" already asks for; nothing here re-derives isolation Playwright
|
|
9
|
-
* already gives structurally.
|
|
2
|
+
* §7 launch/isolated-context/page creation, a thin wrapper over Playwright
|
|
3
|
+
* (see PROPOSAL-B-playwright-for-browser-runtime.md for why Playwright over
|
|
4
|
+
* raw CDP). One `BrowserSession` = one Playwright `BrowserContext` (its own
|
|
5
|
+
* isolation unit) plus its one page.
|
|
10
6
|
*
|
|
11
|
-
* Deliberately does NOT
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* for `ProcessCollector`, for the identical reason: whether session
|
|
17
|
-
* lifecycle becomes Evidence at all is an orchestration-layer question,
|
|
18
|
-
* not this seam's. Both non-goals now have an answer, in each package's
|
|
19
|
-
* own collector — `createProcessCollector` (`@descryy/runtime-controller`)
|
|
20
|
-
* and `BrowserActionCollector.start()` (`browser-action-collector.ts`,
|
|
21
|
-
* PAGE_CREATED) — never here. `startedAt` is captured below only so that
|
|
22
|
-
* answer has a real creation timestamp to report rather than "whenever a
|
|
23
|
-
* collector got around to starting."
|
|
7
|
+
* Deliberately does NOT turn session launch into Evidence -- that's a
|
|
8
|
+
* collector's job (`createProcessCollector` for process lifecycle;
|
|
9
|
+
* `BrowserActionCollector.start()`'s PAGE_CREATED for this), never this
|
|
10
|
+
* module's. `startedAt` is captured below only so that answer has a real
|
|
11
|
+
* creation timestamp to report.
|
|
24
12
|
*/
|
|
25
13
|
import { type Page } from "playwright-core";
|
|
26
14
|
import type { BrowserConfiguration } from "@descryy/runtime-contracts";
|
|
27
15
|
/**
|
|
28
|
-
* RT-068: this
|
|
29
|
-
* `ExecutionConfiguration.browser
|
|
30
|
-
*
|
|
31
|
-
* already refuses elsewhere (see `InstrumentedExecutionInput.execution`'s
|
|
32
|
-
* own comment) -- so this is the contracts type, not a look-alike of it.
|
|
16
|
+
* RT-068: this is the contracts type (`BrowserConfiguration`), not a
|
|
17
|
+
* look-alike declared independently of `ExecutionConfiguration.browser` --
|
|
18
|
+
* two shapes with the same field would drift.
|
|
33
19
|
*/
|
|
34
20
|
export type BrowserSessionOptions = BrowserConfiguration;
|
|
35
21
|
export interface BrowserSession {
|
|
@@ -39,64 +25,47 @@ export interface BrowserSession {
|
|
|
39
25
|
readonly startedAt: string;
|
|
40
26
|
/**
|
|
41
27
|
* False once the page has crashed or closed. Every collector's `start()`
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* `
|
|
45
|
-
*
|
|
46
|
-
* longer run a single action. The `'crash'` event is the only signal
|
|
47
|
-
* that actually fires for that case, so it's tracked here once, for
|
|
48
|
-
* every collector sharing this session, rather than each collector
|
|
49
|
-
* re-attaching its own listener.
|
|
28
|
+
* checks this before reporting available -- `page.isClosed()` alone
|
|
29
|
+
* isn't enough: verified that it still returns false after a real
|
|
30
|
+
* `chrome://crash`. Tracked once here via the `'crash'` event, shared
|
|
31
|
+
* across every collector on this session.
|
|
50
32
|
*/
|
|
51
33
|
isUsable(): boolean;
|
|
52
34
|
close(): Promise<void>;
|
|
53
35
|
/**
|
|
54
|
-
* The finished `recordVideo` file's bytes, or `null`
|
|
55
|
-
*
|
|
36
|
+
* The finished `recordVideo` file's bytes, or `null` if this session
|
|
37
|
+
* wasn't launched with `recordVideo: true`.
|
|
56
38
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* turning a raw fact into Evidence is a collector's job
|
|
60
|
-
* (`BrowserActionCollector.captureVideo()`), never this module's.
|
|
39
|
+
* Not Evidence -- same non-goal as session launch above; that's a
|
|
40
|
+
* collector's job (`BrowserActionCollector.captureVideo()`).
|
|
61
41
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* hang waiting for a close that this method does not itself trigger, so it
|
|
66
|
-
* throws immediately instead of hanging on a caller's mistake.
|
|
42
|
+
* Must be called after `close()` resolves: `Video.path()` doesn't
|
|
43
|
+
* resolve until the context has closed, and this method doesn't trigger
|
|
44
|
+
* that close itself, so it throws immediately rather than hanging.
|
|
67
45
|
*
|
|
68
|
-
* Reads the file
|
|
69
|
-
*
|
|
70
|
-
* already makes at a smaller scale (this module's sibling,
|
|
71
|
-
* `browser-action-collector.ts`), and once the bytes are safely returned
|
|
72
|
-
* here the on-disk copy has no further purpose.
|
|
46
|
+
* Reads the whole file into memory and removes the temp dir -- same
|
|
47
|
+
* tradeoff `screenshot()` makes at a smaller scale.
|
|
73
48
|
*/
|
|
74
49
|
finishedVideo(): Promise<Uint8Array | null>;
|
|
75
50
|
}
|
|
76
51
|
/**
|
|
77
|
-
* Why this exists, and why it
|
|
52
|
+
* Why this exists, and why it's not a throw.
|
|
78
53
|
*
|
|
79
|
-
* This package depends on `playwright-core`, not `playwright
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* and, with it, the guarantee that a browser is present at all.
|
|
54
|
+
* This package depends on `playwright-core`, not `playwright` -- only
|
|
55
|
+
* `playwright`'s postinstall downloads Chromium, and that cost is
|
|
56
|
+
* transitive to everything depending on this package (e.g. `@descryy/mcp`,
|
|
57
|
+
* whose users mostly never call a browser tool): several hundred megabytes
|
|
58
|
+
* for a browser never launched. `playwright-core` drops the download and
|
|
59
|
+
* the guarantee a browser is present.
|
|
86
60
|
*
|
|
87
|
-
* So absence is
|
|
88
|
-
*
|
|
89
|
-
* `
|
|
90
|
-
*
|
|
91
|
-
* caller mapping this onto a user-visible refusal must be able to print the
|
|
92
|
-
* exact command rather than paraphrase it, and a remedy buried in prose is a
|
|
93
|
-
* remedy the caller has to parse back out.
|
|
61
|
+
* So absence is a normal state, shaped like this codebase's other expected
|
|
62
|
+
* inabilities (`ServiceRootLookup`'s `{ found: false, refusal, message }`),
|
|
63
|
+
* plus a `remedy` field so a caller can print the exact fix rather than
|
|
64
|
+
* paraphrase it.
|
|
94
65
|
*
|
|
95
|
-
*
|
|
96
|
-
* `chromium.executablePath()`
|
|
97
|
-
*
|
|
98
|
-
* when that is set -- so the check and the launch below are handed the same
|
|
99
|
-
* string, and cannot disagree about which binary was meant.
|
|
66
|
+
* Checked via `existsSync` on the path `playwright-core` itself computes --
|
|
67
|
+
* `chromium.executablePath()` doesn't verify existence, it returns the path
|
|
68
|
+
* this build would use, so the check and the launch below can't disagree.
|
|
100
69
|
*/
|
|
101
70
|
export interface ChromiumUnavailable {
|
|
102
71
|
readonly refusal: "chromiumNotInstalled";
|
|
@@ -120,10 +89,9 @@ export type BrowserSessionLaunch = {
|
|
|
120
89
|
} & ChromiumUnavailable);
|
|
121
90
|
export declare const CHROMIUM_INSTALL_REMEDY = "npx playwright install chromium";
|
|
122
91
|
/**
|
|
123
|
-
* Resolved at launch time,
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* which is the exact cost `playwright-core` was adopted to remove.
|
|
92
|
+
* Resolved at launch time, not import time -- a module-level check would
|
|
93
|
+
* fail merely importing this package on a machine with no browser, the
|
|
94
|
+
* exact cost `playwright-core` was adopted to remove.
|
|
127
95
|
*/
|
|
128
96
|
export declare function resolveChromiumExecutable(): ChromiumAvailability;
|
|
129
97
|
/** Thrown by `launchBrowserSession` when `resolveChromiumExecutable()` refuses. Carries the refusal whole, so a caller that catches rather than branching still gets the remedy. */
|
|
@@ -134,10 +102,10 @@ export declare class BrowserUnavailableError extends Error {
|
|
|
134
102
|
constructor(unavailable: ChromiumUnavailable);
|
|
135
103
|
}
|
|
136
104
|
/**
|
|
137
|
-
*
|
|
138
|
-
* reportable outcome
|
|
139
|
-
* `
|
|
140
|
-
*
|
|
105
|
+
* Refusal-returning launch. Prefer this where a missing browser is a
|
|
106
|
+
* reportable outcome, not a bug (e.g. an MCP tool's `refused` state).
|
|
107
|
+
* `launchBrowserSession` below is the same call for callers that would
|
|
108
|
+
* only rethrow.
|
|
141
109
|
*/
|
|
142
110
|
export declare function launchBrowserSessionOrRefuse(options?: BrowserSessionOptions): Promise<BrowserSessionLaunch>;
|
|
143
111
|
export declare function launchBrowserSession(options?: BrowserSessionOptions): Promise<BrowserSession>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-session.d.ts","sourceRoot":"","sources":["../src/browser-session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-session.d.ts","sourceRoot":"","sources":["../src/browser-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA+C,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAMzF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,2JAA2J;IAC3J,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,IAAI,OAAO,CAAC;IACpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;;;;;;;;;;;OAaG;IACH,aAAa,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gIAAgI;IAChI,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC7D,CAAC;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAA;CAAE,GAAG,mBAAmB,CAAC,CAAC;AAE1D,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC7D,CAAC;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAA;CAAE,GAAG,mBAAmB,CAAC,CAAC;AAEzD,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,oBAAoB,CAYhE;AAED,oLAAoL;AACpL,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;gBAE5B,WAAW,EAAE,mBAAmB;CAO7C;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAOrH;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,cAAc,CAAC,CAOvG"}
|
package/dist/browser-session.js
CHANGED
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* §7
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* isolation unit -- separate cookies/storage/cache per context) plus its
|
|
7
|
-
* one page, which is what plan §7's "isolated context/session · page
|
|
8
|
-
* creation" already asks for; nothing here re-derives isolation Playwright
|
|
9
|
-
* already gives structurally.
|
|
2
|
+
* §7 launch/isolated-context/page creation, a thin wrapper over Playwright
|
|
3
|
+
* (see PROPOSAL-B-playwright-for-browser-runtime.md for why Playwright over
|
|
4
|
+
* raw CDP). One `BrowserSession` = one Playwright `BrowserContext` (its own
|
|
5
|
+
* isolation unit) plus its one page.
|
|
10
6
|
*
|
|
11
|
-
* Deliberately does NOT
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* for `ProcessCollector`, for the identical reason: whether session
|
|
17
|
-
* lifecycle becomes Evidence at all is an orchestration-layer question,
|
|
18
|
-
* not this seam's. Both non-goals now have an answer, in each package's
|
|
19
|
-
* own collector — `createProcessCollector` (`@descryy/runtime-controller`)
|
|
20
|
-
* and `BrowserActionCollector.start()` (`browser-action-collector.ts`,
|
|
21
|
-
* PAGE_CREATED) — never here. `startedAt` is captured below only so that
|
|
22
|
-
* answer has a real creation timestamp to report rather than "whenever a
|
|
23
|
-
* collector got around to starting."
|
|
7
|
+
* Deliberately does NOT turn session launch into Evidence -- that's a
|
|
8
|
+
* collector's job (`createProcessCollector` for process lifecycle;
|
|
9
|
+
* `BrowserActionCollector.start()`'s PAGE_CREATED for this), never this
|
|
10
|
+
* module's. `startedAt` is captured below only so that answer has a real
|
|
11
|
+
* creation timestamp to report.
|
|
24
12
|
*/
|
|
25
13
|
import { chromium } from "playwright-core";
|
|
26
14
|
import { randomUUID } from "node:crypto";
|
|
@@ -30,10 +18,9 @@ import { tmpdir } from "node:os";
|
|
|
30
18
|
import { join } from "node:path";
|
|
31
19
|
export const CHROMIUM_INSTALL_REMEDY = "npx playwright install chromium";
|
|
32
20
|
/**
|
|
33
|
-
* Resolved at launch time,
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* which is the exact cost `playwright-core` was adopted to remove.
|
|
21
|
+
* Resolved at launch time, not import time -- a module-level check would
|
|
22
|
+
* fail merely importing this package on a machine with no browser, the
|
|
23
|
+
* exact cost `playwright-core` was adopted to remove.
|
|
37
24
|
*/
|
|
38
25
|
export function resolveChromiumExecutable() {
|
|
39
26
|
const executablePath = chromium.executablePath();
|
|
@@ -62,10 +49,10 @@ export class BrowserUnavailableError extends Error {
|
|
|
62
49
|
}
|
|
63
50
|
}
|
|
64
51
|
/**
|
|
65
|
-
*
|
|
66
|
-
* reportable outcome
|
|
67
|
-
* `
|
|
68
|
-
*
|
|
52
|
+
* Refusal-returning launch. Prefer this where a missing browser is a
|
|
53
|
+
* reportable outcome, not a bug (e.g. an MCP tool's `refused` state).
|
|
54
|
+
* `launchBrowserSession` below is the same call for callers that would
|
|
55
|
+
* only rethrow.
|
|
69
56
|
*/
|
|
70
57
|
export async function launchBrowserSessionOrRefuse(options = {}) {
|
|
71
58
|
const chromiumBinary = resolveChromiumExecutable();
|
|
@@ -86,11 +73,8 @@ export async function launchBrowserSession(options = {}) {
|
|
|
86
73
|
async function launchWithExecutable(options, executablePath) {
|
|
87
74
|
const browser = await chromium.launch({ headless: options.headless ?? true, executablePath });
|
|
88
75
|
const sessionId = randomUUID();
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
// is exposed. Created before newContext() because Playwright's
|
|
92
|
-
// `recordVideo.dir` must already exist and be known at context-creation
|
|
93
|
-
// time; there is no way to attach recording after the fact.
|
|
76
|
+
// session-scoped temp dir, never caller-supplied (see BrowserConfiguration.recordVideo).
|
|
77
|
+
// created before newContext(): Playwright's recordVideo.dir must exist and be known at context-creation time.
|
|
94
78
|
const videoDir = options.recordVideo === true ? await mkdtemp(join(tmpdir(), `descry-video-${sessionId}-`)) : null;
|
|
95
79
|
const context = await browser.newContext(videoDir !== null ? { recordVideo: { dir: videoDir } } : {});
|
|
96
80
|
const page = await context.newPage();
|
|
@@ -117,17 +101,13 @@ async function launchWithExecutable(options, executablePath) {
|
|
|
117
101
|
"method does not itself perform). Call session.close() first.");
|
|
118
102
|
}
|
|
119
103
|
const video = page.video();
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
// under that context) -- guarded rather than asserted with `!`,
|
|
123
|
-
// because a null here would otherwise surface as a confusing crash
|
|
124
|
-
// inside readFile(undefined) instead of a clear "nothing to return."
|
|
104
|
+
// shouldn't happen (recordVideo requested implies Playwright attaches a Video) -- guarded rather
|
|
105
|
+
// than asserted with `!`, since a null here would otherwise surface as a confusing crash.
|
|
125
106
|
if (video === null)
|
|
126
107
|
return null;
|
|
127
108
|
const videoFilePath = await video.path();
|
|
128
109
|
const bytes = await readFile(videoFilePath);
|
|
129
|
-
//
|
|
130
|
-
// cleanup failure here (e.g. already removed) must not fail the call.
|
|
110
|
+
// best-effort: bytes are already captured, so a cleanup failure here must not fail the call.
|
|
131
111
|
await rm(videoDir, { recursive: true, force: true }).catch(() => { });
|
|
132
112
|
return bytes;
|
|
133
113
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-session.js","sourceRoot":"","sources":["../src/browser-session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-session.js","sourceRoot":"","sources":["../src/browser-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `Evidence.collectorVersion`
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* from what actually shipped. Same idea as `nodeVersion` elsewhere in this
|
|
6
|
-
* repo (`process.version`, always known, never probed) applied to a
|
|
7
|
-
* package instead of the Node runtime.
|
|
2
|
+
* `Evidence.collectorVersion` source: reads this package's own package.json
|
|
3
|
+
* "version" instead of a hand-duplicated string that can drift. Same idea
|
|
4
|
+
* as `nodeVersion` using `process.version`.
|
|
8
5
|
*/
|
|
9
6
|
export declare const COLLECTOR_VERSION: string;
|
|
10
7
|
//# sourceMappingURL=collector-version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-version.d.ts","sourceRoot":"","sources":["../src/collector-version.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"collector-version.d.ts","sourceRoot":"","sources":["../src/collector-version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,eAAO,MAAM,iBAAiB,EAAE,MAA6E,CAAC"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `Evidence.collectorVersion`
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* from what actually shipped. Same idea as `nodeVersion` elsewhere in this
|
|
6
|
-
* repo (`process.version`, always known, never probed) applied to a
|
|
7
|
-
* package instead of the Node runtime.
|
|
2
|
+
* `Evidence.collectorVersion` source: reads this package's own package.json
|
|
3
|
+
* "version" instead of a hand-duplicated string that can drift. Same idea
|
|
4
|
+
* as `nodeVersion` using `process.version`.
|
|
8
5
|
*/
|
|
9
6
|
import { createRequire } from "node:module";
|
|
10
7
|
const require = createRequire(import.meta.url);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-version.js","sourceRoot":"","sources":["../src/collector-version.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"collector-version.js","sourceRoot":"","sources":["../src/collector-version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,CAAC,MAAM,iBAAiB,GAAY,OAAO,CAAC,iBAAiB,CAAkC,CAAC,OAAO,CAAC"}
|
package/dist/dom-evidence.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* event type -- the frozen `RuntimeEventType` vocabulary has no dedicated
|
|
6
|
-
* DOM-snapshot type, and a DOM fact is naturally "what did the element
|
|
7
|
-
* this action touched look like," not an independent stream.
|
|
2
|
+
* DOM evidence for an action (§8): element/selector/text/value/a11y info.
|
|
3
|
+
* Captured alongside the action, not as its own event type -- no dedicated
|
|
4
|
+
* DOM-snapshot type exists in `RuntimeEventType`.
|
|
8
5
|
*/
|
|
9
6
|
import type { Page } from "playwright-core";
|
|
10
7
|
export interface DomElementSnapshot {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-evidence.d.ts","sourceRoot":"","sources":["../src/dom-evidence.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dom-evidence.d.ts","sourceRoot":"","sources":["../src/dom-evidence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AAWD,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAetG"}
|
package/dist/dom-evidence.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* event type -- the frozen `RuntimeEventType` vocabulary has no dedicated
|
|
6
|
-
* DOM-snapshot type, and a DOM fact is naturally "what did the element
|
|
7
|
-
* this action touched look like," not an independent stream.
|
|
2
|
+
* DOM evidence for an action (§8): element/selector/text/value/a11y info.
|
|
3
|
+
* Captured alongside the action, not as its own event type -- no dedicated
|
|
4
|
+
* DOM-snapshot type exists in `RuntimeEventType`.
|
|
8
5
|
*/
|
|
9
6
|
const VALUE_BEARING_TAGS = new Set(["input", "textarea", "select"]);
|
|
10
7
|
async function safeValue(locator, tagName) {
|
package/dist/dom-evidence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-evidence.js","sourceRoot":"","sources":["../src/dom-evidence.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dom-evidence.js","sourceRoot":"","sources":["../src/dom-evidence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEpE,KAAK,UAAU,SAAS,CAAC,OAAgB,EAAE,OAAsB;IAC/D,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACvE,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAU,EAAE,QAAgB;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC;IAC3F,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3F,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,qBAAqB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7D,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;QACvC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;QAC3B,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KACzC,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;AACnE,CAAC"}
|
|
@@ -1,87 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fetch-initiator capture
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* structural limit, `@descryy/runtime-graph-correlator`).
|
|
2
|
+
* Fetch-initiator capture: page-side half of resolving which frontend
|
|
3
|
+
* function issued an observed request (structural capability alone is
|
|
4
|
+
* `resolveFrontendCallers`'s job, in `@descryy/runtime-graph-correlator`).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* run when Descry is not attached — a same-origin request can pick up a
|
|
12
|
-
* fresh CORS preflight it would not otherwise have had. That side effect is
|
|
13
|
-
* the one `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md`
|
|
14
|
-
* asked a human to sign off on before this was built; nothing here reopens
|
|
15
|
-
* that call.
|
|
6
|
+
* This is a write, not a read: the wrapped fetch() adds a real header
|
|
7
|
+
* (`x-descry-initiator-id`) to a real outgoing request, which can trigger a
|
|
8
|
+
* fresh CORS preflight on a same-origin request. Signed off in
|
|
9
|
+
* `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md`.
|
|
16
10
|
*
|
|
17
|
-
* The call-site stack
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* binding channel (`page.exposeFunction`), straight to `take()` below,
|
|
21
|
-
* keyed by that same id.
|
|
11
|
+
* The call-site stack never travels with application traffic -- only an
|
|
12
|
+
* opaque per-call id does, as the header value. The stack text travels
|
|
13
|
+
* over Playwright's CDP binding (`page.exposeFunction`) to `take()` below.
|
|
22
14
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* binding call, and Chromium's own network stack — happens to land at this
|
|
27
|
-
* process first. That is exactly the kind of timing assumption §27's
|
|
28
|
-
* "similarity must never be treated as causality" rules out. Awaiting the
|
|
29
|
-
* binding call before dispatching `fetch` makes the ordering true by
|
|
30
|
-
* construction instead: the real request cannot be sent until this module
|
|
31
|
-
* has already buffered the stack it will be looked up by.
|
|
15
|
+
* The real fetch() is held until the exposed call returns, so ordering is
|
|
16
|
+
* true by construction rather than a race between the CDP binding and
|
|
17
|
+
* Chromium's network stack (§27: never treat timing as causality).
|
|
32
18
|
*
|
|
33
|
-
* Chromium only
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md` drew, not
|
|
37
|
-
* an oversight of this module.
|
|
19
|
+
* Chromium only (`page.addInitScript`/`page.exposeFunction`), fetch() only
|
|
20
|
+
* (not XMLHttpRequest) -- scope drawn by the proposal above, not an
|
|
21
|
+
* oversight.
|
|
38
22
|
*/
|
|
39
23
|
import type { Page } from "playwright-core";
|
|
40
24
|
export declare const INITIATOR_HEADER_NAME = "x-descry-initiator-id";
|
|
41
25
|
export interface FrontendInitiatorCapture {
|
|
42
26
|
/**
|
|
43
|
-
* Wraps
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* caller wants covered, exactly like `BrowserConsoleCollector`'s own
|
|
47
|
-
* `page.on(...)` registration ordering.
|
|
27
|
+
* Wraps window.fetch in every document from this point forward --
|
|
28
|
+
* addInitScript doesn't reach an already-loaded document. Call before
|
|
29
|
+
* navigating, same ordering as BrowserConsoleCollector's page.on(...).
|
|
48
30
|
*/
|
|
49
31
|
install(page: Page): Promise<void>;
|
|
50
32
|
/**
|
|
51
|
-
* Pops the buffered
|
|
52
|
-
*
|
|
53
|
-
* issued by this capture (a stale id, a different page), or the buffer
|
|
54
|
-
* evicted it under `MAX_BUFFERED_STACKS`. Popped rather than peeked: a
|
|
55
|
-
* captured stack is consumed by the one request it was captured for, and
|
|
56
|
-
* leaving it behind would let a second, unrelated lookup of a reused id
|
|
57
|
-
* (impossible by construction here, but not worth relying on) read
|
|
58
|
-
* another request's call site.
|
|
33
|
+
* Pops the buffered stack for `id`, or undefined if never captured or
|
|
34
|
+
* evicted. Popped not peeked: a captured stack belongs to one request.
|
|
59
35
|
*/
|
|
60
36
|
take(id: string): string | undefined;
|
|
61
37
|
}
|
|
62
38
|
export declare function createFrontendInitiatorCapture(): FrontendInitiatorCapture;
|
|
63
39
|
/**
|
|
64
|
-
* Strips
|
|
65
|
-
*
|
|
66
|
-
* wrapper.
|
|
40
|
+
* Strips descryFetch's own frame from a raw V8 stack so the first
|
|
41
|
+
* remaining frame is the real call site.
|
|
67
42
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* from the synchronous call chain live at capture time, so the innermost
|
|
73
|
-
* frame is deterministically `descryFetch` itself, every time, regardless
|
|
74
|
-
* of what called it. Stripping by *position* (first frame line) rather than
|
|
75
|
-
* by *name* also survives minification of this wrapper's own name, which a
|
|
76
|
-
* name-based strip would not.
|
|
43
|
+
* Works as a fixed "drop first line" rule rather than a name search:
|
|
44
|
+
* Error().stack is captured synchronously as the wrapper's first statement,
|
|
45
|
+
* so the innermost frame is always descryFetch regardless of caller --
|
|
46
|
+
* stripping by position also survives minification of the wrapper's name.
|
|
77
47
|
*
|
|
78
|
-
* Applied to raw text
|
|
79
|
-
*
|
|
80
|
-
* after: `createV8StackTraceParser` already treats frame 0 of whatever it
|
|
81
|
-
* receives as `primaryFrameIndex`, so removing the wrapper's line here
|
|
82
|
-
* means the parser's existing, already-tested convention does the right
|
|
83
|
-
* thing unmodified, instead of teaching every consumer a second index to
|
|
84
|
-
* skip.
|
|
48
|
+
* Applied to raw text before parsing, so createV8StackTraceParser's
|
|
49
|
+
* existing primaryFrameIndex convention (frame 0) just works.
|
|
85
50
|
*/
|
|
86
51
|
export declare function stripInitiatorWrapperFrame(rawStackText: string): string;
|
|
87
52
|
//# sourceMappingURL=frontend-initiator-capture.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-initiator-capture.d.ts","sourceRoot":"","sources":["../src/frontend-initiator-capture.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frontend-initiator-capture.d.ts","sourceRoot":"","sources":["../src/frontend-initiator-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAW7D,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACtC;AAED,wBAAgB,8BAA8B,IAAI,wBAAwB,CAsBzE;AAsCD;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKvE"}
|
|
@@ -1,49 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fetch-initiator capture
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* structural limit, `@descryy/runtime-graph-correlator`).
|
|
2
|
+
* Fetch-initiator capture: page-side half of resolving which frontend
|
|
3
|
+
* function issued an observed request (structural capability alone is
|
|
4
|
+
* `resolveFrontendCallers`'s job, in `@descryy/runtime-graph-correlator`).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* run when Descry is not attached — a same-origin request can pick up a
|
|
12
|
-
* fresh CORS preflight it would not otherwise have had. That side effect is
|
|
13
|
-
* the one `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md`
|
|
14
|
-
* asked a human to sign off on before this was built; nothing here reopens
|
|
15
|
-
* that call.
|
|
6
|
+
* This is a write, not a read: the wrapped fetch() adds a real header
|
|
7
|
+
* (`x-descry-initiator-id`) to a real outgoing request, which can trigger a
|
|
8
|
+
* fresh CORS preflight on a same-origin request. Signed off in
|
|
9
|
+
* `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md`.
|
|
16
10
|
*
|
|
17
|
-
* The call-site stack
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* binding channel (`page.exposeFunction`), straight to `take()` below,
|
|
21
|
-
* keyed by that same id.
|
|
11
|
+
* The call-site stack never travels with application traffic -- only an
|
|
12
|
+
* opaque per-call id does, as the header value. The stack text travels
|
|
13
|
+
* over Playwright's CDP binding (`page.exposeFunction`) to `take()` below.
|
|
22
14
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* binding call, and Chromium's own network stack — happens to land at this
|
|
27
|
-
* process first. That is exactly the kind of timing assumption §27's
|
|
28
|
-
* "similarity must never be treated as causality" rules out. Awaiting the
|
|
29
|
-
* binding call before dispatching `fetch` makes the ordering true by
|
|
30
|
-
* construction instead: the real request cannot be sent until this module
|
|
31
|
-
* has already buffered the stack it will be looked up by.
|
|
15
|
+
* The real fetch() is held until the exposed call returns, so ordering is
|
|
16
|
+
* true by construction rather than a race between the CDP binding and
|
|
17
|
+
* Chromium's network stack (§27: never treat timing as causality).
|
|
32
18
|
*
|
|
33
|
-
* Chromium only
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* `PROPOSAL-observed-frontend-caller-needs-initiator-capture.md` drew, not
|
|
37
|
-
* an oversight of this module.
|
|
19
|
+
* Chromium only (`page.addInitScript`/`page.exposeFunction`), fetch() only
|
|
20
|
+
* (not XMLHttpRequest) -- scope drawn by the proposal above, not an
|
|
21
|
+
* oversight.
|
|
38
22
|
*/
|
|
39
23
|
export const INITIATOR_HEADER_NAME = "x-descry-initiator-id";
|
|
40
24
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* the entire life of the page. FIFO eviction via `Map`'s own insertion
|
|
45
|
-
* order; a stack this old was never going to be claimed by the time
|
|
46
|
-
* something newer needs the room.
|
|
25
|
+
* Cap on stacks buffered but never claimed (stripped header, no matching
|
|
26
|
+
* request) -- otherwise this map grows for the page's whole life. FIFO
|
|
27
|
+
* eviction via Map's own insertion order.
|
|
47
28
|
*/
|
|
48
29
|
const MAX_BUFFERED_STACKS = 2000;
|
|
49
30
|
const CAPTURE_BINDING_NAME = "__descryCaptureInitiatorStack";
|
|
@@ -70,16 +51,10 @@ export function createFrontendInitiatorCapture() {
|
|
|
70
51
|
};
|
|
71
52
|
}
|
|
72
53
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* Every call site outcome degrades to "no id header" or "no functionName"
|
|
78
|
-
* rather than throwing: `bind(...)` is wrapped in its own `.catch`, and a
|
|
79
|
-
* `fetch()` whose `input` is neither a string, `URL`, nor `Request` still
|
|
80
|
-
* reaches `originalFetch` unmodified so the native `TypeError` a caller
|
|
81
|
-
* would have gotten anyway is the one they still get — this wrapper adds a
|
|
82
|
-
* header, it does not change what counts as a valid `fetch()` call.
|
|
54
|
+
* Injected wrapper as a plain string (addInitScript's string form; runs
|
|
55
|
+
* unmodified in the page's own JS engine). Failures degrade silently:
|
|
56
|
+
* bind() is wrapped in .catch, and a non-string/URL/Request fetch input
|
|
57
|
+
* still reaches originalFetch unmodified, so callers get their normal error.
|
|
83
58
|
*/
|
|
84
59
|
function initScriptSource() {
|
|
85
60
|
return `(() => {
|
|
@@ -110,27 +85,16 @@ function initScriptSource() {
|
|
|
110
85
|
}
|
|
111
86
|
const FRAME_LINE = /^\s*at\s/;
|
|
112
87
|
/**
|
|
113
|
-
* Strips
|
|
114
|
-
*
|
|
115
|
-
* wrapper.
|
|
88
|
+
* Strips descryFetch's own frame from a raw V8 stack so the first
|
|
89
|
+
* remaining frame is the real call site.
|
|
116
90
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* from the synchronous call chain live at capture time, so the innermost
|
|
122
|
-
* frame is deterministically `descryFetch` itself, every time, regardless
|
|
123
|
-
* of what called it. Stripping by *position* (first frame line) rather than
|
|
124
|
-
* by *name* also survives minification of this wrapper's own name, which a
|
|
125
|
-
* name-based strip would not.
|
|
91
|
+
* Works as a fixed "drop first line" rule rather than a name search:
|
|
92
|
+
* Error().stack is captured synchronously as the wrapper's first statement,
|
|
93
|
+
* so the innermost frame is always descryFetch regardless of caller --
|
|
94
|
+
* stripping by position also survives minification of the wrapper's name.
|
|
126
95
|
*
|
|
127
|
-
* Applied to raw text
|
|
128
|
-
*
|
|
129
|
-
* after: `createV8StackTraceParser` already treats frame 0 of whatever it
|
|
130
|
-
* receives as `primaryFrameIndex`, so removing the wrapper's line here
|
|
131
|
-
* means the parser's existing, already-tested convention does the right
|
|
132
|
-
* thing unmodified, instead of teaching every consumer a second index to
|
|
133
|
-
* skip.
|
|
96
|
+
* Applied to raw text before parsing, so createV8StackTraceParser's
|
|
97
|
+
* existing primaryFrameIndex convention (frame 0) just works.
|
|
134
98
|
*/
|
|
135
99
|
export function stripInitiatorWrapperFrame(rawStackText) {
|
|
136
100
|
const lines = rawStackText.split(/\r\n|\r|\n/);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-initiator-capture.js","sourceRoot":"","sources":["../src/frontend-initiator-capture.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frontend-initiator-capture.js","sourceRoot":"","sources":["../src/frontend-initiator-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAEjC,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAgB7D,MAAM,UAAU,8BAA8B;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE3C,SAAS,MAAM,CAAC,EAAU,EAAE,SAAiB;QAC3C,IAAI,QAAQ,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,IAAU;YACtB,MAAM,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;YACxD,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,EAAU;YACb,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB;IACvB,OAAO;;;0BAGiB,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC;;;;;;;;;;;;;sBAaxC,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC;;;;;;;;QAQnD,CAAC;AACT,CAAC;AAED,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,YAAoB;IAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,UAAU,KAAK,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC;IAC3C,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Correlation-id extraction from
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `backend-observation`'s `extractCorrelationIds`, which only ever sees
|
|
7
|
-
* unstructured log text and explicitly cuts W3C parsing as a documented
|
|
8
|
-
* V1 gap -- this collector doesn't need that same cut.
|
|
2
|
+
* Correlation-id extraction from HTTP headers -- top three of §10's six
|
|
3
|
+
* levels (trace ID, request ID, W3C trace context). Structured header
|
|
4
|
+
* access makes W3C parsing cheap here, unlike `backend-observation`'s
|
|
5
|
+
* `extractCorrelationIds` (log-text only, documents W3C as a V1 gap).
|
|
9
6
|
*/
|
|
10
7
|
export interface HeaderCorrelationIds {
|
|
11
8
|
readonly traceId: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-correlation.d.ts","sourceRoot":"","sources":["../src/network-correlation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"network-correlation.d.ts","sourceRoot":"","sources":["../src/network-correlation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAUD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,oBAAoB,CAS3G"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Correlation-id extraction from
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `backend-observation`'s `extractCorrelationIds`, which only ever sees
|
|
7
|
-
* unstructured log text and explicitly cuts W3C parsing as a documented
|
|
8
|
-
* V1 gap -- this collector doesn't need that same cut.
|
|
2
|
+
* Correlation-id extraction from HTTP headers -- top three of §10's six
|
|
3
|
+
* levels (trace ID, request ID, W3C trace context). Structured header
|
|
4
|
+
* access makes W3C parsing cheap here, unlike `backend-observation`'s
|
|
5
|
+
* `extractCorrelationIds` (log-text only, documents W3C as a V1 gap).
|
|
9
6
|
*/
|
|
10
7
|
// W3C Trace Context: "00-<32 hex trace-id>-<16 hex parent-id>-<2 hex flags>".
|
|
11
8
|
const TRACEPARENT_PATTERN = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-correlation.js","sourceRoot":"","sources":["../src/network-correlation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"network-correlation.js","sourceRoot":"","sources":["../src/network-correlation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8EAA8E;AAC9E,MAAM,mBAAmB,GAAG,8DAA8D,CAAC;AAO3F,SAAS,WAAW,CAAC,OAAyC,EAAE,KAAwB;IACtF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,OAAyC;IACnF,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IACzE,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE3G,OAAO;QACL,OAAO,EAAE,eAAe,IAAI,UAAU;QACtC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC"}
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RT-023
|
|
3
|
-
*
|
|
4
|
-
* `SourceLocation`s instead of preserved as text.
|
|
2
|
+
* RT-023 collector half: rewrites a script URL to its on-disk file so a
|
|
3
|
+
* page-error stack parses into real `SourceLocation`s instead of text.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* source-map handling and staleness detection, which took real work to get
|
|
10
|
-
* right. Rewriting the URL first lets all of that apply unchanged, where
|
|
11
|
-
* post-processing parsed frames would mean reimplementing it here and
|
|
12
|
-
* keeping two copies honest.
|
|
5
|
+
* Rewrite happens on the stack text before parsing, so the existing
|
|
6
|
+
* `StackTraceParser`/`SourceLocationResolver` (source maps, staleness)
|
|
7
|
+
* apply unchanged rather than being reimplemented here.
|
|
13
8
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* directory — **not** that the file the browser executed came from the
|
|
19
|
-
* checkout in it. The downstream resolver's own existence check is the real
|
|
20
|
-
* refusal point, and an unmapped or non-existent path degrades to the URL
|
|
21
|
-
* itself rather than to a fabricated file. That is RT-031's class again:
|
|
22
|
-
* a match on an observable proxy is not proof of the underlying identity.
|
|
9
|
+
* A successful rewrite proves the origin maps to a directory, not that the
|
|
10
|
+
* executed file came from that checkout (`declaredCwd` is configured, not
|
|
11
|
+
* verified) -- the downstream resolver's existence check is the real
|
|
12
|
+
* refusal point. RT-031's class: a match on a proxy isn't proof of identity.
|
|
23
13
|
*
|
|
24
|
-
* Nothing is rewritten when the resolver refuses,
|
|
25
|
-
*
|
|
26
|
-
* extension, `about:blank`. Those are routine, not failures.
|
|
14
|
+
* Nothing is rewritten when the resolver refuses, is absent, or the URL
|
|
15
|
+
* wasn't spawned by this execution (CDN script, extension, `about:blank`).
|
|
27
16
|
*/
|
|
28
17
|
import type { ServiceRootLookup } from "@descryy/runtime-contracts";
|
|
29
18
|
export type SourceRootResolver = (origin: string) => ServiceRootLookup;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-url-mapping.d.ts","sourceRoot":"","sources":["../src/script-url-mapping.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"script-url-mapping.d.ts","sourceRoot":"","sources":["../src/script-url-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;AAKvE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4GAA4G;IAC5G,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;CACxH;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,kBAAkB,GAAG,SAAS,GAAG,gBAAgB,CAkDxH"}
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RT-023
|
|
3
|
-
*
|
|
4
|
-
* `SourceLocation`s instead of preserved as text.
|
|
2
|
+
* RT-023 collector half: rewrites a script URL to its on-disk file so a
|
|
3
|
+
* page-error stack parses into real `SourceLocation`s instead of text.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* source-map handling and staleness detection, which took real work to get
|
|
10
|
-
* right. Rewriting the URL first lets all of that apply unchanged, where
|
|
11
|
-
* post-processing parsed frames would mean reimplementing it here and
|
|
12
|
-
* keeping two copies honest.
|
|
5
|
+
* Rewrite happens on the stack text before parsing, so the existing
|
|
6
|
+
* `StackTraceParser`/`SourceLocationResolver` (source maps, staleness)
|
|
7
|
+
* apply unchanged rather than being reimplemented here.
|
|
13
8
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* directory — **not** that the file the browser executed came from the
|
|
19
|
-
* checkout in it. The downstream resolver's own existence check is the real
|
|
20
|
-
* refusal point, and an unmapped or non-existent path degrades to the URL
|
|
21
|
-
* itself rather than to a fabricated file. That is RT-031's class again:
|
|
22
|
-
* a match on an observable proxy is not proof of the underlying identity.
|
|
9
|
+
* A successful rewrite proves the origin maps to a directory, not that the
|
|
10
|
+
* executed file came from that checkout (`declaredCwd` is configured, not
|
|
11
|
+
* verified) -- the downstream resolver's existence check is the real
|
|
12
|
+
* refusal point. RT-031's class: a match on a proxy isn't proof of identity.
|
|
23
13
|
*
|
|
24
|
-
* Nothing is rewritten when the resolver refuses,
|
|
25
|
-
*
|
|
26
|
-
* extension, `about:blank`. Those are routine, not failures.
|
|
14
|
+
* Nothing is rewritten when the resolver refuses, is absent, or the URL
|
|
15
|
+
* wasn't spawned by this execution (CDN script, extension, `about:blank`).
|
|
27
16
|
*/
|
|
28
17
|
import { statSync } from "node:fs";
|
|
29
18
|
import { join } from "node:path";
|
|
@@ -35,9 +24,7 @@ export function rewriteScriptUrls(stackText, resolveSourceRoot) {
|
|
|
35
24
|
}
|
|
36
25
|
const outcomes = [];
|
|
37
26
|
const text = stackText.replace(SCRIPT_URL, (match) => {
|
|
38
|
-
//
|
|
39
|
-
// as a URL — `new URL()` would otherwise parse `:12` as part of the
|
|
40
|
-
// path and produce a file that never existed.
|
|
27
|
+
// strip the stack's ":line:column" suffix first -- new URL() would parse ":12" as part of the path.
|
|
41
28
|
const suffix = /:(\d+):(\d+)$/.exec(match);
|
|
42
29
|
const urlText = suffix === null ? match : match.slice(0, match.length - suffix[0].length);
|
|
43
30
|
let url;
|
|
@@ -53,24 +40,12 @@ export function rewriteScriptUrls(stackText, resolveSourceRoot) {
|
|
|
53
40
|
outcomes.push({ url: match, mapped: null, reason: lookup.message });
|
|
54
41
|
return match;
|
|
55
42
|
}
|
|
56
|
-
//
|
|
57
|
-
// leading slash as a fresh root and discard the service's own cwd.
|
|
43
|
+
// url.pathname is always absolute; join would otherwise treat the leading slash as a fresh root and drop declaredCwd.
|
|
58
44
|
const candidate = join(lookup.root.declaredCwd, url.pathname.replace(/^\/+/, ""));
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// yes and this function rewrote a stack frame to a directory no browser
|
|
64
|
-
// ever executed. The downstream `SourceLocationResolver` then reached
|
|
65
|
-
// `readFileSync(directory)`, threw `EISDIR`, and the whole
|
|
66
|
-
// `NETWORK_REQUEST` row was lost with it — an observation discarded to
|
|
67
|
-
// protect a nullable field. `statSync` answers the question that was
|
|
68
|
-
// always being asked (is there a FILE here?) rather than the weaker one
|
|
69
|
-
// that happened to be cheap.
|
|
70
|
-
//
|
|
71
|
-
// `statSync` throws on a missing path where `existsSync` returned false,
|
|
72
|
-
// so the absence case is caught rather than propagated: both branches end
|
|
73
|
-
// in the same refusal, with the reason naming which one it was.
|
|
45
|
+
// isFile(), not existsSync: an inline <script> on a page served at "/" resolves to declaredCwd
|
|
46
|
+
// itself -- a real directory, so existsSync said yes and readFileSync(directory) threw EISDIR,
|
|
47
|
+
// dropping the whole NETWORK_REQUEST row. statSync also catches the missing-path case, so both
|
|
48
|
+
// branches end in the same refusal, with the reason naming which one it was.
|
|
74
49
|
let isFile;
|
|
75
50
|
try {
|
|
76
51
|
isFile = statSync(candidate).isFile();
|
|
@@ -80,11 +55,7 @@ export function rewriteScriptUrls(stackText, resolveSourceRoot) {
|
|
|
80
55
|
return match;
|
|
81
56
|
}
|
|
82
57
|
if (!isFile) {
|
|
83
|
-
//
|
|
84
|
-
// is not a file in it — a directory (the `/` case above), a socket, a
|
|
85
|
-
// device. Reported rather than rewritten: a path that is not a source
|
|
86
|
-
// file is worse than the URL, which at least says truthfully where the
|
|
87
|
-
// browser got it.
|
|
58
|
+
// not a file (dir/socket/device) -- reported rather than rewritten, since that's worse than the honest URL.
|
|
88
59
|
outcomes.push({ url: match, mapped: null, reason: `resolved to "${candidate}", which is not a file on disk` });
|
|
89
60
|
return match;
|
|
90
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-url-mapping.js","sourceRoot":"","sources":["../src/script-url-mapping.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"script-url-mapping.js","sourceRoot":"","sources":["../src/script-url-mapping.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descryy/runtime-browser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser runtime: launch, isolated context, navigation, click/type/wait, DOM inspection, screenshots, console/page-error/network capture, all through the Collector contract (plan \u00a77/\u00a78). See documents/decisions-inbox/PROPOSAL-B-playwright-for-browser-runtime.md for the Playwright-vs-CDP call.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/descryhq-wq/descry-runtime.git",
|
|
10
|
+
"directory": "packages/browser"
|
|
11
|
+
},
|
|
7
12
|
"engines": {
|
|
8
13
|
"node": ">=22.5"
|
|
9
14
|
},
|
|
@@ -24,10 +29,10 @@
|
|
|
24
29
|
"build": "tsc -b"
|
|
25
30
|
},
|
|
26
31
|
"dependencies": {
|
|
27
|
-
"@descryy/runtime-contracts": "0.
|
|
28
|
-
"@descryy/runtime-backend-observation": "0.
|
|
32
|
+
"@descryy/runtime-contracts": "0.3.0",
|
|
33
|
+
"@descryy/runtime-backend-observation": "0.3.0",
|
|
29
34
|
"playwright-core": "^1.62.1",
|
|
30
|
-
"@descryy/runtime-adapter-typescript": "0.
|
|
35
|
+
"@descryy/runtime-adapter-typescript": "0.3.0"
|
|
31
36
|
},
|
|
32
37
|
"devDependencies": {
|
|
33
38
|
"@descryy/runtime-controller": "*",
|