@jobshimo/browser-link 0.36.0 → 0.37.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.
Files changed (38) hide show
  1. package/dist/agent-instructions/content.js +14 -3
  2. package/dist/agent-instructions/content.js.map +1 -1
  3. package/dist/cdp/flow.d.ts +36 -3
  4. package/dist/cdp/flow.js +54 -19
  5. package/dist/cdp/flow.js.map +1 -1
  6. package/dist/cdp/inpage/builders.d.ts +103 -20
  7. package/dist/cdp/inpage/builders.js +199 -52
  8. package/dist/cdp/inpage/builders.js.map +1 -1
  9. package/dist/cdp/inpage/observer.d.ts +36 -7
  10. package/dist/cdp/inpage/observer.js +242 -16
  11. package/dist/cdp/inpage/observer.js.map +1 -1
  12. package/dist/cdp/transport.js +90 -9
  13. package/dist/cdp/transport.js.map +1 -1
  14. package/dist/extension/background.js +91 -13
  15. package/dist/extension/background.js.map +1 -1
  16. package/dist/extension/flow.d.ts +36 -3
  17. package/dist/extension/flow.js +54 -19
  18. package/dist/extension/flow.js.map +1 -1
  19. package/dist/extension/inpage/builders.d.ts +103 -20
  20. package/dist/extension/inpage/builders.js +199 -52
  21. package/dist/extension/inpage/builders.js.map +1 -1
  22. package/dist/extension/inpage/observer.d.ts +36 -7
  23. package/dist/extension/inpage/observer.js +242 -16
  24. package/dist/extension/inpage/observer.js.map +1 -1
  25. package/dist/extension/manifest.json +1 -1
  26. package/dist/map/queries.d.ts +2 -0
  27. package/dist/map/queries.js +23 -1
  28. package/dist/map/queries.js.map +1 -1
  29. package/dist/map/tools.js +26 -4
  30. package/dist/map/tools.js.map +1 -1
  31. package/dist/tools/browser-definitions.js +80 -18
  32. package/dist/tools/browser-definitions.js.map +1 -1
  33. package/dist/tools/browser-dispatch.d.ts +19 -26
  34. package/dist/tools/browser-dispatch.js +152 -14
  35. package/dist/tools/browser-dispatch.js.map +1 -1
  36. package/dist/tools/server-instructions.js +14 -3
  37. package/dist/tools/server-instructions.js.map +1 -1
  38. package/package.json +1 -1
@@ -28,7 +28,7 @@ import { OBSERVER_GLOBAL } from './observer.js';
28
28
  * injected verbatim into `buildSnapshotJs`, `buildFindJs` and `buildStateJs`.
29
29
  * The observer global is looked up ONCE per evaluation and used only when it
30
30
  * is present, not torn down, and exposes `refFor`:
31
- * - `refOf(el)` returns the observer's `e<N>` ref for `el`, or `null`;
31
+ * - `refOf(el)` returns the observer's `<doc_tag>:e<N>` ref for `el`, or `null`;
32
32
  * - `withDocId(result)` adds `doc_id` to `result` and returns it;
33
33
  * - `snapshotStore()` returns the observer when it keeps snapshot records
34
34
  * (`recordSnapshot` / `getSnapshot`, used by `snapshot({ since })`), else
@@ -68,6 +68,53 @@ export const PAGE_OBSERVER_JS = `
68
68
  return null;
69
69
  }
70
70
  `;
71
+ /**
72
+ * In-page action-target resolution (spec v4 §6.3), injected after
73
+ * `DEEP_QUERY_JS` and `PAGE_OBSERVER_JS` into the builders that take a
74
+ * `selector` or a `ref` (click, type, focus, element rect, `wait_for` by
75
+ * ref, `find` by ref):
76
+ * `resolveTarget(opts)` with a non-empty `opts.ref` asks the observer
77
+ * (`resolveRefDetailed`, which re-resolves a replaced node by its semantic
78
+ * key) and answers `{ ok: true, el, reresolved }`, `{ ok: false, reason:
79
+ * 'ref-stale', ref, doc_id }` or `{ ok: false, reason: 'observer-unavailable'
80
+ * }`; otherwise it resolves `opts.selector` exactly as the selector builders
81
+ * always did (`invalid-selector` checked against `document` first, then
82
+ * `deepQueryFirst`, `not-found`). Kept out of `PAGE_OBSERVER_JS` so the
83
+ * snapshot and state sources do not carry code they never call.
84
+ */
85
+ export const RESOLVE_TARGET_JS = `
86
+ function resolveTarget(opts) {
87
+ if (typeof opts.ref === 'string' && opts.ref.length > 0) {
88
+ if (!pageObserver || typeof pageObserver.resolveRefDetailed !== 'function') {
89
+ return { ok: false, reason: 'observer-unavailable' };
90
+ }
91
+ let found = null;
92
+ try {
93
+ found = pageObserver.resolveRefDetailed(opts.ref);
94
+ } catch (e) {
95
+ found = null;
96
+ }
97
+ if (!found || !found.el) return withDocId({ ok: false, reason: 'ref-stale', ref: opts.ref });
98
+ return { ok: true, el: found.el, reresolved: found.reresolved === true };
99
+ }
100
+ try {
101
+ document.querySelector(opts.selector);
102
+ } catch (e) {
103
+ return { ok: false, reason: 'invalid-selector', error: e && e.message ? e.message : String(e) };
104
+ }
105
+ const el = deepQueryFirst(opts.selector);
106
+ if (!el) return { ok: false, reason: 'not-found' };
107
+ return { ok: true, el: el, reresolved: false };
108
+ }
109
+ `;
110
+ /** JSON for the `selector` / `ref` pair, embedded as data in the built
111
+ * source; `ref` is included only when given so a selector build keeps the
112
+ * same options object as before. */
113
+ function targetJson(opts) {
114
+ return typeof opts.ref === 'string' && opts.ref.length > 0
115
+ ? { selector: opts.selector, ref: opts.ref }
116
+ : { selector: opts.selector };
117
+ }
71
118
  export function buildSnapshotJs(opts = {}) {
72
119
  const optsJson = JSON.stringify({
73
120
  withinSelector: typeof opts.within_selector === 'string' ? opts.within_selector : null,
@@ -260,6 +307,16 @@ export function buildSnapshotJs(opts = {}) {
260
307
  })()
261
308
  `;
262
309
  }
310
+ /** Only the documented key fields reach the built source, as JSON data. */
311
+ function findKeyJson(key) {
312
+ return Array.isArray(key.path)
313
+ ? {
314
+ role: key.role,
315
+ name: key.name,
316
+ path: key.path.map((step) => ({ tag: step.tag, index: step.index })),
317
+ }
318
+ : { role: key.role, name: key.name };
319
+ }
263
320
  export function buildFindJs(opts) {
264
321
  const optsJson = JSON.stringify({
265
322
  text: opts.text,
@@ -267,13 +324,98 @@ export function buildFindJs(opts) {
267
324
  exact: opts.exact === true,
268
325
  candidateLimit: 5,
269
326
  nearMissLimit: 3,
327
+ ...(typeof opts.ref === 'string' && opts.ref.length > 0 ? { ref: opts.ref } : {}),
328
+ ...(opts.key ? { key: findKeyJson(opts.key) } : {}),
270
329
  });
271
330
  return `
272
331
  (() => {
273
332
  ${DEEP_QUERY_JS}
274
333
  ${DOM_HELPERS_JS}
275
334
  ${PAGE_OBSERVER_JS}
335
+ ${typeof opts.ref === 'string' && opts.ref.length > 0 ? RESOLVE_TARGET_JS : ''}
276
336
  const opts = ${optsJson};
337
+ function semanticKeyOf(el) {
338
+ if (!pageObserver || typeof pageObserver.semanticKeyFor !== 'function') return null;
339
+ try {
340
+ const key = pageObserver.semanticKeyFor(el);
341
+ return key && typeof key === 'object' ? key : null;
342
+ } catch (e) {
343
+ return null;
344
+ }
345
+ }
346
+ function singleMatch(el, ref, reresolved) {
347
+ const center = viewportCenterOf(el);
348
+ const selInfo = genSelectorInfo(el);
349
+ const result = { matched: true, selector: selInfo.selector };
350
+ if (ref) result.ref = ref;
351
+ result.coords = {
352
+ x: Math.round(center.x),
353
+ y: Math.round(center.y),
354
+ };
355
+ result.tag = el.tagName.toLowerCase();
356
+ result.text = shortText(el);
357
+ if (selInfo.ambiguous) result.ambiguous = true;
358
+ const frame = frameSelectorFor(el);
359
+ if (frame) result.frame = frame;
360
+ if (reresolved) result.reresolved = true;
361
+ const key = semanticKeyOf(el);
362
+ if (key) result.semantic_key = key;
363
+ return withDocId(result);
364
+ }
365
+ if (typeof opts.ref === 'string') {
366
+ const target = resolveTarget(opts);
367
+ if (!target.ok) {
368
+ const failure = { matched: false, reason: target.reason, ref: opts.ref };
369
+ return withDocId(failure);
370
+ }
371
+ return singleMatch(target.el, opts.ref, target.reresolved);
372
+ }
373
+ if (opts.key) {
374
+ if (!pageObserver || typeof pageObserver.semanticKeyFor !== 'function') {
375
+ return { matched: false, reason: 'observer-unavailable' };
376
+ }
377
+ const wanted = opts.key;
378
+ const candidates = [];
379
+ for (const el of deepQueryAll('*')) {
380
+ const key = semanticKeyOf(el);
381
+ if (key && key.role === wanted.role && key.name === wanted.name) {
382
+ candidates.push({ el: el, path: Array.isArray(key.path) ? key.path : [] });
383
+ }
384
+ }
385
+ const count = candidates.length;
386
+ const shared = 'key: ' + count + ' candidates share role and name; ';
387
+ let picked = null;
388
+ let error = count > 1 ? shared + 'pass path to disambiguate' : null;
389
+ if (!Array.isArray(wanted.path)) {
390
+ if (count === 1) picked = candidates[0].el;
391
+ } else {
392
+ // Same rule as the observer's re-resolution: identical tag path and
393
+ // exactly one such candidate; identical rows are refused, never guessed.
394
+ let sameTags = 0;
395
+ let only = null;
396
+ for (const c of candidates) {
397
+ if (c.path.length !== wanted.path.length) continue;
398
+ let same = true;
399
+ for (let i = 0; i < c.path.length && same; i++) {
400
+ if (c.path[i].tag !== wanted.path[i].tag) same = false;
401
+ }
402
+ if (!same) continue;
403
+ sameTags++;
404
+ only = c.el;
405
+ }
406
+ if (sameTags === 1) {
407
+ picked = only;
408
+ } else if (sameTags > 1) {
409
+ error = 'key: ' + sameTags + ' candidates share role, name and tag path';
410
+ } else if (count > 0) {
411
+ error = shared + 'none has the same tag path';
412
+ }
413
+ }
414
+ if (picked) return singleMatch(picked, refOf(picked), false);
415
+ const failure = { matched: false, reason: 'not-found' };
416
+ if (error) failure.error = error;
417
+ return withDocId(failure);
418
+ }
277
419
  const needle = opts.text.toLowerCase();
278
420
  const needleTokens = needle.split(/[^a-z0-9]+/).filter(Boolean);
279
421
  const ROLE_SELECTORS = {
@@ -392,37 +534,21 @@ export function buildFindJs(opts) {
392
534
  });
393
535
  }
394
536
  const el = matches[0];
395
- const center = viewportCenterOf(el);
396
- const selInfo = genSelectorInfo(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),
403
- };
404
- result.tag = el.tagName.toLowerCase();
405
- result.text = shortText(el);
406
- if (selInfo.ambiguous) result.ambiguous = true;
407
- const frame = frameSelectorFor(el);
408
- if (frame) result.frame = frame;
409
- return withDocId(result);
537
+ return singleMatch(el, refOf(el), false);
410
538
  })()
411
539
  `;
412
540
  }
413
541
  export function buildClickResolveJs(opts) {
414
- const optsJson = JSON.stringify({ selector: opts.selector, force: opts.force });
542
+ const optsJson = JSON.stringify({ ...targetJson(opts), force: opts.force });
415
543
  return `
416
544
  (() => {
417
545
  ${DEEP_QUERY_JS}
546
+ ${PAGE_OBSERVER_JS}
547
+ ${RESOLVE_TARGET_JS}
418
548
  const opts = ${optsJson};
419
- try {
420
- document.querySelector(opts.selector);
421
- } catch (e) {
422
- return { ok: false, reason: 'invalid-selector', error: e && e.message ? e.message : String(e) };
423
- }
424
- const el = deepQueryFirst(opts.selector);
425
- if (!el) return { ok: false, reason: 'not-found' };
549
+ const target = resolveTarget(opts);
550
+ if (!target.ok) return target;
551
+ const el = target.el;
426
552
  const chain = frameElementChain(el);
427
553
  for (const fe of chain) {
428
554
  if (fe.scrollIntoView) fe.scrollIntoView({ block: 'center', inline: 'center' });
@@ -437,41 +563,59 @@ export function buildClickResolveJs(opts) {
437
563
  const result = { ok: true, x: center.x, y: center.y, tag };
438
564
  const hit = occlusion.allowed ? occlusion.hit : occlusion.blocker;
439
565
  if (hit) result.hit_element = hit;
566
+ if (target.reresolved) result.reresolved = true;
440
567
  return result;
441
568
  })()
442
569
  `;
443
570
  }
444
571
  export function buildTypeResolveJs(opts) {
445
- const optsJson = JSON.stringify({ selector: opts.selector });
572
+ const optsJson = JSON.stringify(targetJson(opts));
446
573
  return `
447
574
  (() => {
448
575
  ${DEEP_QUERY_JS}
576
+ ${PAGE_OBSERVER_JS}
577
+ ${RESOLVE_TARGET_JS}
449
578
  const opts = ${optsJson};
450
- try {
451
- document.querySelector(opts.selector);
452
- } catch (e) {
453
- return { ok: false, reason: 'invalid-selector', error: e && e.message ? e.message : String(e) };
454
- }
455
- const el = deepQueryFirst(opts.selector);
456
- if (!el) return { ok: false, reason: 'not-found' };
579
+ const target = resolveTarget(opts);
580
+ if (!target.ok) return target;
581
+ const el = target.el;
457
582
  el.focus();
458
583
  ${opts.clear ? "if ('value' in el) { el.value = ''; el.dispatchEvent(new Event('input', { bubbles: true })); }" : ''}
459
- return { ok: true };
584
+ return target.reresolved ? { ok: true, reresolved: true } : { ok: true };
460
585
  })()`;
461
586
  }
462
587
  export function buildFocusJs(opts) {
463
- const optsJson = JSON.stringify({ selector: opts.selector });
588
+ const optsJson = JSON.stringify(targetJson(opts));
464
589
  return `
465
590
  (() => {
466
591
  ${DEEP_QUERY_JS}
592
+ ${PAGE_OBSERVER_JS}
593
+ ${RESOLVE_TARGET_JS}
467
594
  const opts = ${optsJson};
468
- const el = deepQueryFirst(opts.selector);
469
- if (!el) return false;
470
- el.focus();
471
- return true;
595
+ const target = resolveTarget(opts);
596
+ const byRef = typeof opts.ref === 'string';
597
+ if (!target.ok) return byRef ? target : false;
598
+ target.el.focus();
599
+ if (!byRef) return true;
600
+ return target.reresolved ? { ok: true, reresolved: true } : { ok: true };
472
601
  })()`;
473
602
  }
474
- export function buildWaitForSelectorJs(selector, condition) {
603
+ export function buildWaitForSelectorJs(target, condition) {
604
+ if (typeof target !== 'string') {
605
+ const refOptsJson = JSON.stringify({ ref: target.ref, condition });
606
+ return `
607
+ (() => {
608
+ ${DEEP_QUERY_JS}
609
+ ${PAGE_OBSERVER_JS}
610
+ ${RESOLVE_TARGET_JS}
611
+ const opts = ${refOptsJson};
612
+ const target = resolveTarget(opts);
613
+ if (!target.ok && target.reason === 'observer-unavailable') return target;
614
+ const el = target.ok ? target.el : null;
615
+ ${WAIT_FOR_CONDITION_JS}
616
+ })()`;
617
+ }
618
+ const selector = target;
475
619
  const optsJson = JSON.stringify({ selector, condition });
476
620
  return `
477
621
  (() => {
@@ -479,7 +623,12 @@ export function buildWaitForSelectorJs(selector, condition) {
479
623
  const opts = ${optsJson};
480
624
  document.querySelector(opts.selector);
481
625
  const el = deepQueryFirst(opts.selector);
482
- if (opts.condition === 'attached') return Boolean(el);
626
+ ${WAIT_FOR_CONDITION_JS}
627
+ })()`;
628
+ }
629
+ /** The condition check shared by both `wait_for` probe targets; `el` is
630
+ * the resolved element or `null`. */
631
+ const WAIT_FOR_CONDITION_JS = `if (opts.condition === 'attached') return Boolean(el);
483
632
  if (opts.condition === 'detached') return !el;
484
633
  const wantHidden = opts.condition === 'hidden';
485
634
  if (!el) return wantHidden;
@@ -488,22 +637,18 @@ export function buildWaitForSelectorJs(selector, condition) {
488
637
  if (s.display === 'none' || s.visibility === 'hidden' || s.opacity === '0') return wantHidden;
489
638
  const r = el.getBoundingClientRect();
490
639
  const shown = r.width > 0 && r.height > 0;
491
- return wantHidden ? !shown : shown;
492
- })()`;
493
- }
640
+ return wantHidden ? !shown : shown;`;
494
641
  export function buildElementRectJs(opts) {
495
- const optsJson = JSON.stringify({ selector: opts.selector });
642
+ const optsJson = JSON.stringify(targetJson(opts));
496
643
  return `
497
644
  (() => {
498
645
  ${DEEP_QUERY_JS}
646
+ ${PAGE_OBSERVER_JS}
647
+ ${RESOLVE_TARGET_JS}
499
648
  const opts = ${optsJson};
500
- try {
501
- document.querySelector(opts.selector);
502
- } catch (e) {
503
- return { ok: false, reason: 'invalid-selector', error: e && e.message ? e.message : String(e) };
504
- }
505
- const el = deepQueryFirst(opts.selector);
506
- if (!el) return { ok: false, reason: 'not-found' };
649
+ const target = resolveTarget(opts);
650
+ if (!target.ok) return target;
651
+ const el = target.el;
507
652
  const chain = frameElementChain(el);
508
653
  // behavior 'instant' overrides CSS scroll-behavior: smooth, which would
509
654
  // leave the rect below stale while the scroll is still animating.
@@ -528,13 +673,15 @@ export function buildElementRectJs(opts) {
528
673
  scrollX = top.scrollX || 0;
529
674
  scrollY = top.scrollY || 0;
530
675
  } catch (_) {}
531
- return {
676
+ const result = {
532
677
  ok: true,
533
678
  x: offsetX + rect.left + scrollX,
534
679
  y: offsetY + rect.top + scrollY,
535
680
  width: rect.width,
536
681
  height: rect.height,
537
682
  };
683
+ if (target.reresolved) result.reresolved = true;
684
+ return result;
538
685
  })()`;
539
686
  }
540
687
  export function buildSettleJs(opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/cdp/inpage/builders.ts"],"names":[],"mappings":"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"}
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 = 2;
14
+ export declare const OBSERVER_VERSION = 3;
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. */
@@ -33,10 +33,30 @@ export interface ObserverInstallOpts {
33
33
  * `{ ok: true, installed, version, doc_id, coverage }`.
34
34
  *
35
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()`
36
+ * `<doc_tag>:e<N>` (`doc_tag` = the first 6 characters of `doc_id`, N
37
+ * monotonic per document instance, from 1) the first time an element is seen
38
+ * and reuses it while the node lives; `resolveRef(ref)` returns the element
39
+ * while it is connected, else `null`. Refs are only valid for the document
40
+ * instance that issued them: a ref whose tag is not this instance's tag, or a
41
+ * bare `e<N>` with no tag, is `null` everywhere (resolve, re-resolve, key)
42
+ * without consulting the registries. Neither method throws.
43
+ *
44
+ * Secondary identity (spec v4 §5.6, decided by lab 10): `semanticKeyFor(el)`
45
+ * returns `{ role, name, path }` — role from the `role` attribute or a small
46
+ * implicit table, accessible-ish name (aria-label, aria-labelledby, associated
47
+ * label, text ≤ 80 chars, placeholder, title, button-like input value) and up
48
+ * to 8 `{ tag, index }` ancestor steps (1-based same-tag sibling index, a
49
+ * shadow boundary as `{ tag: '#shadow', index: 0 }`). `refFor` stores the key
50
+ * when it issues a ref. `resolveRefDetailed(ref)` returns `{ el, reresolved }`:
51
+ * the live node with `reresolved: false`, else the element with the same role,
52
+ * name and tag-only path when exactly one exists, rebinding the ref to it
53
+ * (`reresolved: true`); zero or several candidates give `null` (sibling
54
+ * indices are kept in the key as data but never pick among candidates). Candidates come from the document, every open shadow root reachable
55
+ * from it, and every root the `attachShadow` patch observed (closed ones
56
+ * included); closed roots attached before install are not reachable.
57
+ * `resolveRef(ref)` is `resolveRefDetailed(ref)?.el ?? null`. `keyForRef(ref)`
58
+ * returns a copy of the stored key or `null`. None of these throws.
59
+ * `nextSnapshotId()`
40
60
  * issues `<doc_id>:s<N>` (N monotonic per document instance, from 1) for each
41
61
  * `snapshot` result and returns `null` once the instance is torn down; the
42
62
  * `doc_id` prefix lets a stale id from another document be rejected.
@@ -65,10 +85,19 @@ export declare function buildObserverChangesJs(mark: number, docId?: string): st
65
85
  /**
66
86
  * Build the ref-resolve expression, for tests and debugging. Evaluates to
67
87
  * `{ 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' }`.
88
+ * document that is still connected — plus `reresolved: true` when the node was
89
+ * gone and the ref was just rebound by its semantic key —
90
+ * `{ ok: true, found: false }` when it is unknown or stale, or
91
+ * `{ ok: false, reason: 'observer-unavailable' }`.
70
92
  */
71
93
  export declare function buildObserverRefResolveJs(ref: string): string;
94
+ /**
95
+ * Build the semantic-key read expression. Evaluates to `{ ok: true, key }`
96
+ * with the `{ role, name, path }` stored when `ref` was issued, `{ ok: true,
97
+ * key: null }` for a ref this document instance does not know, or
98
+ * `{ ok: false, reason: 'observer-unavailable' }`.
99
+ */
100
+ export declare function buildObserverSemanticKeyJs(ref: string): string;
72
101
  /**
73
102
  * Build the teardown expression: disconnects every observer, restores the
74
103
  * `attachShadow` and `history` patches when they are still the observer's,