@jobshimo/browser-link 0.35.0 → 0.36.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/dist/agent-instructions/content.js +10 -0
- package/dist/agent-instructions/content.js.map +1 -1
- package/dist/cdp/inpage/builders.d.ts +52 -3
- package/dist/cdp/inpage/builders.js +176 -35
- package/dist/cdp/inpage/builders.js.map +1 -1
- package/dist/cdp/inpage/observer.d.ts +21 -1
- package/dist/cdp/inpage/observer.js +106 -2
- package/dist/cdp/inpage/observer.js.map +1 -1
- package/dist/cdp/transport.js +1 -0
- package/dist/cdp/transport.js.map +1 -1
- package/dist/extension/background.js +1 -0
- package/dist/extension/background.js.map +1 -1
- package/dist/extension/inpage/builders.d.ts +52 -3
- package/dist/extension/inpage/builders.js +176 -35
- package/dist/extension/inpage/builders.js.map +1 -1
- package/dist/extension/inpage/observer.d.ts +21 -1
- package/dist/extension/inpage/observer.js +106 -2
- package/dist/extension/inpage/observer.js.map +1 -1
- package/dist/extension/manifest.json +1 -1
- package/dist/tools/browser-definitions.js +13 -3
- package/dist/tools/browser-definitions.js.map +1 -1
- package/dist/tools/browser-dispatch.js +14 -2
- package/dist/tools/browser-dispatch.js.map +1 -1
- package/dist/tools/server-instructions.js +10 -0
- package/dist/tools/server-instructions.js.map +1 -1
- package/package.json +1 -1
|
@@ -170,6 +170,16 @@ function body() {
|
|
|
170
170
|
' Filters are applied IN-page so the dropped material never travels back.',
|
|
171
171
|
' Pass `exclude:["nav","footer"]` to skip repeated landmarks; pass',
|
|
172
172
|
' `within_selector` when only one region matters.',
|
|
173
|
+
'- Looking at the same view again → take ONE full `browser.snapshot` per',
|
|
174
|
+
' view, keep its `snapshot_id`, and pass it as `since` for every later',
|
|
175
|
+
' look: `browser.snapshot({ since })` returns only `added` / `removed` /',
|
|
176
|
+
' `changed` entries instead of the whole page. On `since_status:',
|
|
177
|
+
' "doc-changed"` (or `evicted`, `observer-unavailable`) you already got',
|
|
178
|
+
' the full snapshot back: keep its new `snapshot_id`. A changed',
|
|
179
|
+
' neighbour can be listed because its selector changed — use the current',
|
|
180
|
+
' one. `ref` (`e<N>`) on entries is an element handle valid only for the',
|
|
181
|
+
' `doc_id` that issued it; for now it is informational, not an action',
|
|
182
|
+
' target.',
|
|
173
183
|
'- Reading N values → ONE `browser.evaluate` returning an object:',
|
|
174
184
|
' `(() => ({ a: document.querySelector("#a").value, b: ... }))()`.',
|
|
175
185
|
' Never N separate evaluates for N reads.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/agent-instructions/content.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/agent-instructions/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-page access to the page observer's element identity (spec v4 §5.6),
|
|
3
|
+
* injected verbatim into `buildSnapshotJs`, `buildFindJs` and `buildStateJs`.
|
|
4
|
+
* The observer global is looked up ONCE per evaluation and used only when it
|
|
5
|
+
* is present, not torn down, and exposes `refFor`:
|
|
6
|
+
* - `refOf(el)` returns the observer's `e<N>` ref for `el`, or `null`;
|
|
7
|
+
* - `withDocId(result)` adds `doc_id` to `result` and returns it;
|
|
8
|
+
* - `snapshotStore()` returns the observer when it keeps snapshot records
|
|
9
|
+
* (`recordSnapshot` / `getSnapshot`, used by `snapshot({ since })`), else
|
|
10
|
+
* `null`.
|
|
11
|
+
* Without the observer (injection failed, pre-observer document) all are
|
|
12
|
+
* no-ops, so every result is byte-identical to the pre-ref output.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PAGE_OBSERVER_JS: string;
|
|
1
15
|
/**
|
|
2
16
|
* Build the snapshot expression. Filters are applied INSIDE the page so the
|
|
3
17
|
* server never receives the dropped material at all — that's where the token
|
|
@@ -17,18 +31,50 @@
|
|
|
17
31
|
* a computed `pointer-events: none` element can never receive a real click
|
|
18
32
|
* (see the helper's comment in `dom-helpers.ts`). Headings and the text
|
|
19
33
|
* dump keep plain `isVisible`, so such elements still contribute text.
|
|
34
|
+
*
|
|
35
|
+
* With the page observer installed (see `PAGE_OBSERVER_JS`), each
|
|
36
|
+
* interactive entry carries `ref` right after `selector`, and the result
|
|
37
|
+
* carries `doc_id` and `snapshot_id` (`<doc_id>:s<N>`, one per call). Without
|
|
38
|
+
* it the output is unchanged.
|
|
39
|
+
*
|
|
40
|
+
* Every snapshot taken with the observer is recorded by it (the last 4 per
|
|
41
|
+
* document; the first 500 entries keyed by ref, each with a hash = the entry
|
|
42
|
+
* serialised without `ref`). `since: <snapshot_id>` then answers with a diff
|
|
43
|
+
* against that record instead of the full list:
|
|
44
|
+
* { title, url, doc_id, snapshot_id, since, added, removed, changed,
|
|
45
|
+
* overflow?, headings?, text? }
|
|
46
|
+
* `added` are entries whose ref is new, `removed` are `{ ref, tag, text? }`
|
|
47
|
+
* of refs gone (capped at 500), `changed` are current entries whose hash
|
|
48
|
+
* differs. `max_interactive` applies AFTER diffing to `added` then `changed`;
|
|
49
|
+
* `overflow` counts what it dropped. `headings` / `text` appear only when
|
|
50
|
+
* `only_interactive` is false and they differ from the recorded ones.
|
|
51
|
+
* When the diff cannot be made the result is the full snapshot plus `since`
|
|
52
|
+
* and `since_status`:
|
|
53
|
+
* - `observer-unavailable`: no observer (no `doc_id` / `snapshot_id`);
|
|
54
|
+
* - `doc-changed`: `snapshot_id` is `<doc_id>:s<N>`, and the part of
|
|
55
|
+
* `since` before its LAST `:` is not the current `doc_id` (or `since` has
|
|
56
|
+
* no `:`), so it came from another document; the store is not consulted;
|
|
57
|
+
* - `evicted`: the prefix is the current `doc_id` but the id is not among
|
|
58
|
+
* the last 4 records (evicted, or never issued).
|
|
59
|
+
* A `within_selector` miss ignores `since` and keeps the miss shape (plus
|
|
60
|
+
* `doc_id`).
|
|
20
61
|
*/
|
|
21
62
|
export interface SnapshotOpts {
|
|
22
63
|
within_selector?: string;
|
|
23
64
|
only_interactive?: boolean;
|
|
24
65
|
exclude?: string[];
|
|
25
66
|
max_interactive?: number;
|
|
67
|
+
/** `snapshot_id` of an earlier snapshot of this document to diff against. */
|
|
68
|
+
since?: string;
|
|
26
69
|
}
|
|
27
70
|
export declare function buildSnapshotJs(opts?: SnapshotOpts): string;
|
|
28
71
|
/** Build the find-by-text expression. Returns one of:
|
|
29
|
-
* { matched: true, selector, coords:{x,y}, tag, text, frame?, ambiguous? }
|
|
30
|
-
* { matched: false, reason: 'not-found', error?, near_misses?: [{text,selector,role?}] }
|
|
31
|
-
* { matched: false, reason: 'multiple-matches', candidates: [{selector,text,tag}] }
|
|
72
|
+
* { matched: true, selector, ref?, coords:{x,y}, tag, text, frame?, ambiguous?, doc_id? }
|
|
73
|
+
* { matched: false, reason: 'not-found', error?, near_misses?: [{text,selector,ref?,role?}], doc_id? }
|
|
74
|
+
* { matched: false, reason: 'multiple-matches', candidates: [{selector,ref?,text,tag}], doc_id? }
|
|
75
|
+
*
|
|
76
|
+
* `ref` and `doc_id` are present only when the page observer is installed
|
|
77
|
+
* (see `PAGE_OBSERVER_JS`).
|
|
32
78
|
*
|
|
33
79
|
* Role-aware: when `role` is provided, only elements whose explicit ARIA
|
|
34
80
|
* role or implicit role match are considered. When omitted, the search
|
|
@@ -233,5 +279,8 @@ export declare function buildExpectProbeJs(opts: ExpectProbeOpts): string;
|
|
|
233
279
|
* `focused` beyond `<body>`, no `dialogs` when none are open, and no
|
|
234
280
|
* `scroll` when the page is at its default (0,0) position — token-lean by
|
|
235
281
|
* construction, matching the omit-falsy convention the other builders use.
|
|
282
|
+
*
|
|
283
|
+
* With the page observer installed (see `PAGE_OBSERVER_JS`), `focused`
|
|
284
|
+
* carries `ref` right after `selector` and the result carries `doc_id`.
|
|
236
285
|
*/
|
|
237
286
|
export declare function buildStateJs(): string;
|
|
@@ -22,6 +22,52 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { DEEP_QUERY_JS } from './deep-query.js';
|
|
24
24
|
import { DOM_HELPERS_JS } from './dom-helpers.js';
|
|
25
|
+
import { OBSERVER_GLOBAL } from './observer.js';
|
|
26
|
+
/**
|
|
27
|
+
* In-page access to the page observer's element identity (spec v4 §5.6),
|
|
28
|
+
* injected verbatim into `buildSnapshotJs`, `buildFindJs` and `buildStateJs`.
|
|
29
|
+
* The observer global is looked up ONCE per evaluation and used only when it
|
|
30
|
+
* is present, not torn down, and exposes `refFor`:
|
|
31
|
+
* - `refOf(el)` returns the observer's `e<N>` ref for `el`, or `null`;
|
|
32
|
+
* - `withDocId(result)` adds `doc_id` to `result` and returns it;
|
|
33
|
+
* - `snapshotStore()` returns the observer when it keeps snapshot records
|
|
34
|
+
* (`recordSnapshot` / `getSnapshot`, used by `snapshot({ since })`), else
|
|
35
|
+
* `null`.
|
|
36
|
+
* Without the observer (injection failed, pre-observer document) all are
|
|
37
|
+
* no-ops, so every result is byte-identical to the pre-ref output.
|
|
38
|
+
*/
|
|
39
|
+
export const PAGE_OBSERVER_JS = `
|
|
40
|
+
const pageObserver = (() => {
|
|
41
|
+
try {
|
|
42
|
+
const g = window[${JSON.stringify(OBSERVER_GLOBAL)}];
|
|
43
|
+
if (g && !g.dead && typeof g.refFor === 'function') return g;
|
|
44
|
+
} catch (e) {}
|
|
45
|
+
return null;
|
|
46
|
+
})();
|
|
47
|
+
function refOf(el) {
|
|
48
|
+
if (!pageObserver) return null;
|
|
49
|
+
try {
|
|
50
|
+
const ref = pageObserver.refFor(el);
|
|
51
|
+
return typeof ref === 'string' ? ref : null;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function withDocId(result) {
|
|
57
|
+
if (pageObserver && typeof pageObserver.doc_id === 'string') result.doc_id = pageObserver.doc_id;
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
function snapshotStore() {
|
|
61
|
+
if (
|
|
62
|
+
pageObserver &&
|
|
63
|
+
typeof pageObserver.recordSnapshot === 'function' &&
|
|
64
|
+
typeof pageObserver.getSnapshot === 'function'
|
|
65
|
+
) {
|
|
66
|
+
return pageObserver;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
25
71
|
export function buildSnapshotJs(opts = {}) {
|
|
26
72
|
const optsJson = JSON.stringify({
|
|
27
73
|
withinSelector: typeof opts.within_selector === 'string' ? opts.within_selector : null,
|
|
@@ -30,23 +76,25 @@ export function buildSnapshotJs(opts = {}) {
|
|
|
30
76
|
maxInteractive: typeof opts.max_interactive === 'number' && opts.max_interactive > 0
|
|
31
77
|
? Math.min(opts.max_interactive, 500)
|
|
32
78
|
: 120,
|
|
79
|
+
since: typeof opts.since === 'string' ? opts.since : null,
|
|
33
80
|
});
|
|
34
81
|
return `
|
|
35
82
|
(() => {
|
|
36
83
|
${DEEP_QUERY_JS}
|
|
37
84
|
${DOM_HELPERS_JS}
|
|
85
|
+
${PAGE_OBSERVER_JS}
|
|
38
86
|
const opts = ${optsJson};
|
|
39
87
|
let root = document;
|
|
40
88
|
let notice = '';
|
|
41
89
|
if (opts.withinSelector) {
|
|
42
90
|
const sub = deepQueryFirst(opts.withinSelector);
|
|
43
91
|
if (!sub) {
|
|
44
|
-
return {
|
|
92
|
+
return withDocId({
|
|
45
93
|
title: document.title,
|
|
46
94
|
url: location.href,
|
|
47
95
|
interactive: [],
|
|
48
96
|
notice: 'within_selector did not match any element',
|
|
49
|
-
};
|
|
97
|
+
});
|
|
50
98
|
}
|
|
51
99
|
root = sub;
|
|
52
100
|
}
|
|
@@ -89,6 +137,8 @@ export function buildSnapshotJs(opts = {}) {
|
|
|
89
137
|
const role = el.getAttribute('role') || tag;
|
|
90
138
|
const selInfo = genSelectorInfo(el);
|
|
91
139
|
const entry = { tag, role, selector: selInfo.selector };
|
|
140
|
+
const ref = refOf(el);
|
|
141
|
+
if (ref) entry.ref = ref;
|
|
92
142
|
if (selInfo.ambiguous) entry.ambiguous = true;
|
|
93
143
|
const txt = shortText(el);
|
|
94
144
|
if (txt) entry.text = txt;
|
|
@@ -108,26 +158,105 @@ export function buildSnapshotJs(opts = {}) {
|
|
|
108
158
|
if (frame) entry.frame = frame;
|
|
109
159
|
interactive.push(entry);
|
|
110
160
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
url: location.href,
|
|
114
|
-
interactive: interactive.slice(0, opts.maxInteractive),
|
|
115
|
-
};
|
|
161
|
+
let headings = null;
|
|
162
|
+
let visibleText = '';
|
|
116
163
|
if (!opts.onlyInteractive) {
|
|
117
|
-
const
|
|
164
|
+
const found = [];
|
|
118
165
|
deepQueryAll('h1, h2, h3', root).forEach((h) => {
|
|
119
166
|
if (!isVisible(h)) return;
|
|
120
167
|
if (inExcludedLandmark(h)) return;
|
|
121
168
|
const t = shortText(h);
|
|
122
|
-
if (t)
|
|
169
|
+
if (t) found.push({ level: h.tagName, text: t });
|
|
123
170
|
});
|
|
124
|
-
|
|
171
|
+
headings = found.slice(0, 30);
|
|
125
172
|
const textRoot = (root === document) ? (document.body || document) : root;
|
|
126
|
-
|
|
173
|
+
visibleText = (textRoot && textRoot.innerText) ? textRoot.innerText.slice(0, 4000) : '';
|
|
174
|
+
}
|
|
175
|
+
let snapshotId = null;
|
|
176
|
+
if (withDocId({}).doc_id && typeof pageObserver.nextSnapshotId === 'function') {
|
|
177
|
+
const issued = pageObserver.nextSnapshotId();
|
|
178
|
+
if (typeof issued === 'string') snapshotId = issued;
|
|
179
|
+
}
|
|
180
|
+
function fullResult() {
|
|
181
|
+
const result = {
|
|
182
|
+
title: document.title,
|
|
183
|
+
url: location.href,
|
|
184
|
+
interactive: interactive.slice(0, opts.maxInteractive),
|
|
185
|
+
};
|
|
186
|
+
if (headings) result.headings = headings;
|
|
127
187
|
if (visibleText) result.text = visibleText;
|
|
188
|
+
if (notice) result.notice = notice;
|
|
189
|
+
withDocId(result);
|
|
190
|
+
if (snapshotId) result.snapshot_id = snapshotId;
|
|
191
|
+
return result;
|
|
128
192
|
}
|
|
129
|
-
|
|
130
|
-
|
|
193
|
+
// Record every snapshot (with or without since) so a later call can diff
|
|
194
|
+
// against it. Entries are keyed by ref; the hash is the entry serialised
|
|
195
|
+
// without its ref, in emission order. Capped at the first 500 entries.
|
|
196
|
+
const store = snapshotId ? snapshotStore() : null;
|
|
197
|
+
// A snapshot_id is \`<doc_id>:s<N>\`: a since whose prefix (before the LAST
|
|
198
|
+
// ':') is not this document's doc_id, or that has no ':', came from another
|
|
199
|
+
// document and is never looked up.
|
|
200
|
+
const sinceCut = opts.since === null ? -1 : opts.since.lastIndexOf(':');
|
|
201
|
+
const sinceSameDoc =
|
|
202
|
+
sinceCut >= 0 && withDocId({}).doc_id === opts.since.slice(0, sinceCut);
|
|
203
|
+
const previous = store && sinceSameDoc ? store.getSnapshot(opts.since) : null;
|
|
204
|
+
const current = new Map();
|
|
205
|
+
const headingsHash = headings ? JSON.stringify(headings) : null;
|
|
206
|
+
const textHash = opts.onlyInteractive ? null : visibleText;
|
|
207
|
+
if (store) {
|
|
208
|
+
for (const entry of interactive) {
|
|
209
|
+
if (current.size >= 500) break;
|
|
210
|
+
if (typeof entry.ref !== 'string') continue;
|
|
211
|
+
const copy = {};
|
|
212
|
+
for (const key of Object.keys(entry)) if (key !== 'ref') copy[key] = entry[key];
|
|
213
|
+
current.set(entry.ref, { hash: JSON.stringify(copy), entry });
|
|
214
|
+
}
|
|
215
|
+
store.recordSnapshot(snapshotId, { entries: current, headings_hash: headingsHash, text_hash: textHash });
|
|
216
|
+
}
|
|
217
|
+
if (opts.since === null) return fullResult();
|
|
218
|
+
if (!store) {
|
|
219
|
+
const result = fullResult();
|
|
220
|
+
result.since = opts.since;
|
|
221
|
+
result.since_status = 'observer-unavailable';
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
if (!previous || !previous.entries || typeof previous.entries.get !== 'function') {
|
|
225
|
+
const result = fullResult();
|
|
226
|
+
result.since = opts.since;
|
|
227
|
+
result.since_status = sinceSameDoc ? 'evicted' : 'doc-changed';
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
const added = [];
|
|
231
|
+
const changed = [];
|
|
232
|
+
const removed = [];
|
|
233
|
+
current.forEach((item, ref) => {
|
|
234
|
+
const old = previous.entries.get(ref);
|
|
235
|
+
if (!old) added.push(item.entry);
|
|
236
|
+
else if (old.hash !== item.hash) changed.push(item.entry);
|
|
237
|
+
});
|
|
238
|
+
previous.entries.forEach((item, ref) => {
|
|
239
|
+
if (current.has(ref) || removed.length >= 500) return;
|
|
240
|
+
const gone = { ref, tag: item.entry.tag };
|
|
241
|
+
if (item.entry.text) gone.text = item.entry.text;
|
|
242
|
+
removed.push(gone);
|
|
243
|
+
});
|
|
244
|
+
// max_interactive applies after diffing (added first, then changed), so
|
|
245
|
+
// a window shift never masquerades as change.
|
|
246
|
+
const listed = added.concat(changed);
|
|
247
|
+
const kept = listed.slice(0, opts.maxInteractive);
|
|
248
|
+
const diff = withDocId({ title: document.title, url: location.href });
|
|
249
|
+
diff.snapshot_id = snapshotId;
|
|
250
|
+
diff.since = opts.since;
|
|
251
|
+
diff.added = kept.slice(0, Math.min(added.length, kept.length));
|
|
252
|
+
diff.removed = removed;
|
|
253
|
+
diff.changed = kept.slice(diff.added.length);
|
|
254
|
+
if (listed.length > kept.length) diff.overflow = listed.length - kept.length;
|
|
255
|
+
if (!opts.onlyInteractive) {
|
|
256
|
+
if (headingsHash !== previous.headings_hash) diff.headings = headings;
|
|
257
|
+
if (textHash !== previous.text_hash) diff.text = visibleText;
|
|
258
|
+
}
|
|
259
|
+
return diff;
|
|
131
260
|
})()
|
|
132
261
|
`;
|
|
133
262
|
}
|
|
@@ -143,6 +272,7 @@ export function buildFindJs(opts) {
|
|
|
143
272
|
(() => {
|
|
144
273
|
${DEEP_QUERY_JS}
|
|
145
274
|
${DOM_HELPERS_JS}
|
|
275
|
+
${PAGE_OBSERVER_JS}
|
|
146
276
|
const opts = ${optsJson};
|
|
147
277
|
const needle = opts.text.toLowerCase();
|
|
148
278
|
const needleTokens = needle.split(/[^a-z0-9]+/).filter(Boolean);
|
|
@@ -203,6 +333,8 @@ export function buildFindJs(opts) {
|
|
|
203
333
|
}
|
|
204
334
|
function toNearMiss(el) {
|
|
205
335
|
const entry = { text: snippetOf(el), selector: genSelector(el) };
|
|
336
|
+
const ref = refOf(el);
|
|
337
|
+
if (ref) entry.ref = ref;
|
|
206
338
|
const roleAttr = el.getAttribute('role');
|
|
207
339
|
if (roleAttr) entry.role = roleAttr;
|
|
208
340
|
return entry;
|
|
@@ -235,44 +367,46 @@ export function buildFindJs(opts) {
|
|
|
235
367
|
' but none with role "' + opts.role + '"' +
|
|
236
368
|
(closest ? ' — closest: ' + describeForError(closest) + ' "' + snippetOf(closest) + '"' : '');
|
|
237
369
|
result.near_misses = ranked.map(toNearMiss);
|
|
238
|
-
return result;
|
|
370
|
+
return withDocId(result);
|
|
239
371
|
}
|
|
240
372
|
const ranked = rankCandidates(broadAll);
|
|
241
373
|
if (ranked.length > 0) result.near_misses = ranked.map(toNearMiss);
|
|
242
|
-
return result;
|
|
374
|
+
return withDocId(result);
|
|
243
375
|
}
|
|
244
376
|
const ranked = rankCandidates(all);
|
|
245
377
|
if (ranked.length > 0) result.near_misses = ranked.map(toNearMiss);
|
|
246
|
-
return result;
|
|
378
|
+
return withDocId(result);
|
|
247
379
|
}
|
|
248
380
|
if (matches.length > 1) {
|
|
249
|
-
return {
|
|
381
|
+
return withDocId({
|
|
250
382
|
matched: false,
|
|
251
383
|
reason: 'multiple-matches',
|
|
252
|
-
candidates: matches.slice(0, opts.candidateLimit).map((el) =>
|
|
253
|
-
selector: genSelector(el)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
384
|
+
candidates: matches.slice(0, opts.candidateLimit).map((el) => {
|
|
385
|
+
const candidate = { selector: genSelector(el) };
|
|
386
|
+
const ref = refOf(el);
|
|
387
|
+
if (ref) candidate.ref = ref;
|
|
388
|
+
candidate.text = shortText(el);
|
|
389
|
+
candidate.tag = el.tagName.toLowerCase();
|
|
390
|
+
return candidate;
|
|
391
|
+
}),
|
|
392
|
+
});
|
|
258
393
|
}
|
|
259
394
|
const el = matches[0];
|
|
260
395
|
const center = viewportCenterOf(el);
|
|
261
396
|
const selInfo = genSelectorInfo(el);
|
|
262
|
-
const result = {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
tag: el.tagName.toLowerCase(),
|
|
270
|
-
text: shortText(el),
|
|
397
|
+
const result = { matched: true, selector: selInfo.selector };
|
|
398
|
+
const ref = refOf(el);
|
|
399
|
+
if (ref) result.ref = ref;
|
|
400
|
+
result.coords = {
|
|
401
|
+
x: Math.round(center.x),
|
|
402
|
+
y: Math.round(center.y),
|
|
271
403
|
};
|
|
404
|
+
result.tag = el.tagName.toLowerCase();
|
|
405
|
+
result.text = shortText(el);
|
|
272
406
|
if (selInfo.ambiguous) result.ambiguous = true;
|
|
273
407
|
const frame = frameSelectorFor(el);
|
|
274
408
|
if (frame) result.frame = frame;
|
|
275
|
-
return result;
|
|
409
|
+
return withDocId(result);
|
|
276
410
|
})()
|
|
277
411
|
`;
|
|
278
412
|
}
|
|
@@ -569,12 +703,16 @@ export function buildExpectProbeJs(opts) {
|
|
|
569
703
|
* `focused` beyond `<body>`, no `dialogs` when none are open, and no
|
|
570
704
|
* `scroll` when the page is at its default (0,0) position — token-lean by
|
|
571
705
|
* construction, matching the omit-falsy convention the other builders use.
|
|
706
|
+
*
|
|
707
|
+
* With the page observer installed (see `PAGE_OBSERVER_JS`), `focused`
|
|
708
|
+
* carries `ref` right after `selector` and the result carries `doc_id`.
|
|
572
709
|
*/
|
|
573
710
|
export function buildStateJs() {
|
|
574
711
|
return `
|
|
575
712
|
(() => {
|
|
576
713
|
${DEEP_QUERY_JS}
|
|
577
714
|
${DOM_HELPERS_JS}
|
|
715
|
+
${PAGE_OBSERVER_JS}
|
|
578
716
|
function deepActiveElement() {
|
|
579
717
|
let el = document.activeElement;
|
|
580
718
|
let guard = 0;
|
|
@@ -635,7 +773,10 @@ export function buildStateJs() {
|
|
|
635
773
|
const active = deepActiveElement();
|
|
636
774
|
if (active && active !== document.body && active.tagName) {
|
|
637
775
|
const selInfo = genSelectorInfo(active);
|
|
638
|
-
const focused = { selector: selInfo.selector
|
|
776
|
+
const focused = { selector: selInfo.selector };
|
|
777
|
+
const ref = refOf(active);
|
|
778
|
+
if (ref) focused.ref = ref;
|
|
779
|
+
focused.tag = active.tagName.toLowerCase();
|
|
639
780
|
if (selInfo.ambiguous) focused.ambiguous = true;
|
|
640
781
|
result.focused = focused;
|
|
641
782
|
}
|
|
@@ -655,7 +796,7 @@ export function buildStateJs() {
|
|
|
655
796
|
const scrollY = Math.round(window.scrollY);
|
|
656
797
|
if (scrollX !== 0 || scrollY !== 0) result.scroll = { x: scrollX, y: scrollY };
|
|
657
798
|
|
|
658
|
-
return result;
|
|
799
|
+
return withDocId(result);
|
|
659
800
|
})()
|
|
660
801
|
`;
|
|
661
802
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/cdp/inpage/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/cdp/inpage/builders.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* `cdp/builders-parity.test.ts` checks the built output.
|
|
12
12
|
*/
|
|
13
13
|
/** Bump whenever the in-page protocol (global shape, messages, methods) changes. */
|
|
14
|
-
export declare const OBSERVER_VERSION =
|
|
14
|
+
export declare const OBSERVER_VERSION = 2;
|
|
15
15
|
/** Name of the `Runtime.addBinding` function the observer pushes messages through. */
|
|
16
16
|
export declare const OBSERVER_BINDING = "__blPageObserverPush";
|
|
17
17
|
/** Well-known global that holds the installed observer instance. */
|
|
@@ -31,6 +31,19 @@ export interface ObserverInstallOpts {
|
|
|
31
31
|
* `Page.addScriptToEvaluateOnNewDocument` source and as a one-off
|
|
32
32
|
* `Runtime.evaluate` expression, which evaluates to
|
|
33
33
|
* `{ ok: true, installed, version, doc_id, coverage }`.
|
|
34
|
+
*
|
|
35
|
+
* The instance also owns element identity (spec v4 §5.6): `refFor(el)` issues
|
|
36
|
+
* `e<N>` (monotonic per document instance, from `e1`) the first time an
|
|
37
|
+
* element is seen and reuses it while the node lives; `resolveRef(ref)`
|
|
38
|
+
* returns the element while it is connected, else `null`. Refs are only valid
|
|
39
|
+
* for the `doc_id` that issued them. Neither method throws. `nextSnapshotId()`
|
|
40
|
+
* issues `<doc_id>:s<N>` (N monotonic per document instance, from 1) for each
|
|
41
|
+
* `snapshot` result and returns `null` once the instance is torn down; the
|
|
42
|
+
* `doc_id` prefix lets a stale id from another document be rejected.
|
|
43
|
+
* `recordSnapshot(id, record)` keeps the last 4 snapshot records per document
|
|
44
|
+
* instance (oldest evicted first) for `snapshot({ since })`; `getSnapshot(id)`
|
|
45
|
+
* returns the record or `null` when unknown or evicted. The record is opaque
|
|
46
|
+
* here. Both are inert after teardown, which clears the store.
|
|
34
47
|
*/
|
|
35
48
|
export declare function buildObserverInstallJs(opts?: ObserverInstallOpts): string;
|
|
36
49
|
/**
|
|
@@ -49,6 +62,13 @@ export declare function buildObserverMarkJs(): string;
|
|
|
49
62
|
* baseline; or `{ ok: false, reason: 'observer-unavailable' | 'doc-changed' }`.
|
|
50
63
|
*/
|
|
51
64
|
export declare function buildObserverChangesJs(mark: number, docId?: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Build the ref-resolve expression, for tests and debugging. Evaluates to
|
|
67
|
+
* `{ ok: true, found: true, tag }` when `ref` names an element of the current
|
|
68
|
+
* document that is still connected, `{ ok: true, found: false }` when it is
|
|
69
|
+
* unknown or stale, or `{ ok: false, reason: 'observer-unavailable' }`.
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildObserverRefResolveJs(ref: string): string;
|
|
52
72
|
/**
|
|
53
73
|
* Build the teardown expression: disconnects every observer, restores the
|
|
54
74
|
* `attachShadow` and `history` patches when they are still the observer's,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* `cdp/builders-parity.test.ts` checks the built output.
|
|
12
12
|
*/
|
|
13
13
|
/** Bump whenever the in-page protocol (global shape, messages, methods) changes. */
|
|
14
|
-
export const OBSERVER_VERSION =
|
|
14
|
+
export const OBSERVER_VERSION = 2;
|
|
15
15
|
/** Name of the `Runtime.addBinding` function the observer pushes messages through. */
|
|
16
16
|
export const OBSERVER_BINDING = '__blPageObserverPush';
|
|
17
17
|
/** Well-known global that holds the installed observer instance. */
|
|
@@ -30,6 +30,19 @@ function clampInt(value, fallback, min, max) {
|
|
|
30
30
|
* `Page.addScriptToEvaluateOnNewDocument` source and as a one-off
|
|
31
31
|
* `Runtime.evaluate` expression, which evaluates to
|
|
32
32
|
* `{ ok: true, installed, version, doc_id, coverage }`.
|
|
33
|
+
*
|
|
34
|
+
* The instance also owns element identity (spec v4 §5.6): `refFor(el)` issues
|
|
35
|
+
* `e<N>` (monotonic per document instance, from `e1`) the first time an
|
|
36
|
+
* element is seen and reuses it while the node lives; `resolveRef(ref)`
|
|
37
|
+
* returns the element while it is connected, else `null`. Refs are only valid
|
|
38
|
+
* for the `doc_id` that issued them. Neither method throws. `nextSnapshotId()`
|
|
39
|
+
* issues `<doc_id>:s<N>` (N monotonic per document instance, from 1) for each
|
|
40
|
+
* `snapshot` result and returns `null` once the instance is torn down; the
|
|
41
|
+
* `doc_id` prefix lets a stale id from another document be rejected.
|
|
42
|
+
* `recordSnapshot(id, record)` keeps the last 4 snapshot records per document
|
|
43
|
+
* instance (oldest evicted first) for `snapshot({ since })`; `getSnapshot(id)`
|
|
44
|
+
* returns the record or `null` when unknown or evicted. The record is opaque
|
|
45
|
+
* here. Both are inert after teardown, which clears the store.
|
|
33
46
|
*/
|
|
34
47
|
export function buildObserverInstallJs(opts = {}) {
|
|
35
48
|
const optsJson = JSON.stringify({
|
|
@@ -71,6 +84,18 @@ export function buildObserverInstallJs(opts = {}) {
|
|
|
71
84
|
};
|
|
72
85
|
const observers = [];
|
|
73
86
|
const observed = new WeakSet();
|
|
87
|
+
let refs = new WeakMap();
|
|
88
|
+
const refNodes = new Map();
|
|
89
|
+
let refSeq = 0;
|
|
90
|
+
let snapshotSeq = 0;
|
|
91
|
+
// Last SNAPSHOT_KEEP snapshot records (opaque to the observer; the snapshot
|
|
92
|
+
// builder owns their shape), keyed by snapshot_id in insertion order.
|
|
93
|
+
const SNAPSHOT_KEEP = 4;
|
|
94
|
+
const snapshots = new Map();
|
|
95
|
+
// WeakRef keeps the registry from pinning removed nodes; the fallback only
|
|
96
|
+
// matters on engines without it (Chrome has it since 84).
|
|
97
|
+
const holdWeakly =
|
|
98
|
+
typeof WeakRef === 'function' ? (el) => new WeakRef(el) : (el) => ({ deref: () => el });
|
|
74
99
|
const round = (n) => Math.round(n * 10) / 10;
|
|
75
100
|
|
|
76
101
|
function push(message) {
|
|
@@ -257,6 +282,53 @@ export function buildObserverInstallJs(opts = {}) {
|
|
|
257
282
|
|
|
258
283
|
g.flush = flush;
|
|
259
284
|
|
|
285
|
+
g.refFor = function (el) {
|
|
286
|
+
try {
|
|
287
|
+
if (g.dead || !el || el.nodeType !== 1) return null;
|
|
288
|
+
let ref = refs.get(el);
|
|
289
|
+
if (!ref) {
|
|
290
|
+
ref = 'e' + ++refSeq;
|
|
291
|
+
refs.set(el, ref);
|
|
292
|
+
}
|
|
293
|
+
// Same node, same ref: re-register one pruned while it was detached.
|
|
294
|
+
if (!refNodes.has(ref)) refNodes.set(ref, holdWeakly(el));
|
|
295
|
+
return ref;
|
|
296
|
+
} catch (e) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
g.resolveRef = function (ref) {
|
|
302
|
+
try {
|
|
303
|
+
if (typeof ref !== 'string') return null;
|
|
304
|
+
const held = refNodes.get(ref);
|
|
305
|
+
if (!held) return null;
|
|
306
|
+
const el = held.deref();
|
|
307
|
+
if (el && el.isConnected) return el;
|
|
308
|
+
refNodes.delete(ref);
|
|
309
|
+
return null;
|
|
310
|
+
} catch (e) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
g.nextSnapshotId = function () {
|
|
316
|
+
if (g.dead) return null;
|
|
317
|
+
return g.doc_id + ':s' + ++snapshotSeq;
|
|
318
|
+
};
|
|
319
|
+
g.recordSnapshot = function (id, record) {
|
|
320
|
+
if (g.dead || typeof id !== 'string') return;
|
|
321
|
+
snapshots.delete(id);
|
|
322
|
+
snapshots.set(id, record);
|
|
323
|
+
while (snapshots.size > SNAPSHOT_KEEP) snapshots.delete(snapshots.keys().next().value);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
g.getSnapshot = function (id) {
|
|
327
|
+
if (g.dead || typeof id !== 'string') return null;
|
|
328
|
+
const record = snapshots.get(id);
|
|
329
|
+
return record === undefined ? null : record;
|
|
330
|
+
};
|
|
331
|
+
|
|
260
332
|
g.mark = function () {
|
|
261
333
|
flush();
|
|
262
334
|
const mark = g.seq;
|
|
@@ -337,6 +409,10 @@ export function buildObserverInstallJs(opts = {}) {
|
|
|
337
409
|
window.removeEventListener('popstate', onNav);
|
|
338
410
|
window.removeEventListener('hashchange', onNav);
|
|
339
411
|
g.baselines.clear();
|
|
412
|
+
refs = new WeakMap();
|
|
413
|
+
refNodes.clear();
|
|
414
|
+
snapshotSeq = 0;
|
|
415
|
+
snapshots.clear();
|
|
340
416
|
if (window[opts.key] === g) {
|
|
341
417
|
try { delete window[opts.key]; } catch (e) {}
|
|
342
418
|
}
|
|
@@ -379,9 +455,37 @@ export function buildObserverMarkJs() {
|
|
|
379
455
|
*/
|
|
380
456
|
export function buildObserverChangesJs(mark, docId) {
|
|
381
457
|
const markJson = JSON.stringify(clampInt(mark, 0, 0, Number.MAX_SAFE_INTEGER));
|
|
382
|
-
const docJson = typeof docId === 'string' && docId.length > 0 ?
|
|
458
|
+
const docJson = typeof docId === 'string' && docId.length > 0 ? jsStringLiteral(docId) : 'null';
|
|
383
459
|
return callInstance(`g.changes(${markJson}, ${docJson})`);
|
|
384
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* A string literal safe to embed in JS source. `JSON.stringify` alone leaves
|
|
463
|
+
* U+2028 / U+2029 (line terminators in older JS grammars) and `<` (which can
|
|
464
|
+
* close a surrounding `<script>`) unescaped; this escapes them as `\uXXXX`,
|
|
465
|
+
* which parses back to the same string.
|
|
466
|
+
*/
|
|
467
|
+
function jsStringLiteral(value) {
|
|
468
|
+
// The two separators are written as char codes so this source file never
|
|
469
|
+
// carries them raw; the replacement is the six-character escape sequence.
|
|
470
|
+
const lineSeparator = String.fromCharCode(0x2028);
|
|
471
|
+
const paragraphSeparator = String.fromCharCode(0x2029);
|
|
472
|
+
return JSON.stringify(value)
|
|
473
|
+
.split(lineSeparator)
|
|
474
|
+
.join('\\u2028')
|
|
475
|
+
.split(paragraphSeparator)
|
|
476
|
+
.join('\\u2029')
|
|
477
|
+
.replace(/</g, '\\u003c');
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Build the ref-resolve expression, for tests and debugging. Evaluates to
|
|
481
|
+
* `{ ok: true, found: true, tag }` when `ref` names an element of the current
|
|
482
|
+
* document that is still connected, `{ ok: true, found: false }` when it is
|
|
483
|
+
* unknown or stale, or `{ ok: false, reason: 'observer-unavailable' }`.
|
|
484
|
+
*/
|
|
485
|
+
export function buildObserverRefResolveJs(ref) {
|
|
486
|
+
const refJson = jsStringLiteral(typeof ref === 'string' ? ref : '');
|
|
487
|
+
return callInstance(`((el) => el ? { ok: true, found: true, tag: el.localName || String(el.nodeName).toLowerCase() } : { ok: true, found: false })(g.resolveRef(${refJson}))`);
|
|
488
|
+
}
|
|
385
489
|
/**
|
|
386
490
|
* Build the teardown expression: disconnects every observer, restores the
|
|
387
491
|
* `attachShadow` and `history` patches when they are still the observer's,
|