@swmansion/argent 0.14.0 → 0.14.1-next.1
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/bin/argent-android-devtools-0.1.0.apk +0 -0
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/tvos-ax-service +0 -0
- package/bin/darwin/tvos-hid-daemon +0 -0
- package/dist/tool-server.cjs +244 -42
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tvos/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tvos/libKeyboardPatch.dylib +0 -0
- package/dylibs/tvos/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +1 -1
|
Binary file
|
package/bin/darwin/ax-service
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/tool-server.cjs
CHANGED
|
@@ -121358,7 +121358,7 @@ init_zod();
|
|
|
121358
121358
|
|
|
121359
121359
|
// ../tool-server/src/tools/describe/platforms/chromium.ts
|
|
121360
121360
|
var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
121361
|
-
const MAX_DEPTH =
|
|
121361
|
+
const MAX_DEPTH = 60;
|
|
121362
121362
|
const MAX_NODES = 5000;
|
|
121363
121363
|
let nodeBudget = MAX_NODES;
|
|
121364
121364
|
let truncated = false;
|
|
@@ -121366,23 +121366,57 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121366
121366
|
const h = window.innerHeight;
|
|
121367
121367
|
if (!w || !h) return JSON.stringify({ tree: null, error: "viewport is zero" });
|
|
121368
121368
|
|
|
121369
|
+
// Native prototype accessors, captured once. HTMLFormElement (and HTMLObject/Embed)
|
|
121370
|
+
// is [LegacyOverrideBuiltins]: a control named the same as an inherited member shadows
|
|
121371
|
+
// it on the <form>, so el.children returns the control element (not iterable) and
|
|
121372
|
+
// el.getAttribute returns an element (not a function) \u2014 both throw and abort the whole
|
|
121373
|
+
// walk, the exact crash class this walker must avoid. A prototype accessor is never
|
|
121374
|
+
// shadowed by a form's named properties, so EVERY inherited member read on a possibly-
|
|
121375
|
+
// clobbered element (methods and getters alike) goes through these via .call(el).
|
|
121376
|
+
//
|
|
121377
|
+
// protoGetter reads the accessor's getter defensively: if the descriptor is ever
|
|
121378
|
+
// absent (a page can delete/redefine a DOM prototype member), it falls back to a
|
|
121379
|
+
// direct property read so one missing accessor degrades a single node instead of a
|
|
121380
|
+
// \`.get\` on \`undefined\` throwing at script top and aborting the entire describe.
|
|
121381
|
+
function protoGetter(proto, prop) {
|
|
121382
|
+
const d = Object.getOwnPropertyDescriptor(proto, prop);
|
|
121383
|
+
return d && d.get ? d.get : function () { return this[prop]; };
|
|
121384
|
+
}
|
|
121385
|
+
const getChildNodes = protoGetter(Node.prototype, "childNodes");
|
|
121386
|
+
const getNodeType = protoGetter(Node.prototype, "nodeType");
|
|
121387
|
+
const getNodeValue = protoGetter(Node.prototype, "nodeValue");
|
|
121388
|
+
const getTextContent = protoGetter(Node.prototype, "textContent");
|
|
121389
|
+
const getTagName = protoGetter(Element.prototype, "tagName");
|
|
121390
|
+
const getChildrenEls = protoGetter(Element.prototype, "children");
|
|
121391
|
+
const getShadowRoot = protoGetter(Element.prototype, "shadowRoot");
|
|
121392
|
+
const getScrollHeight = protoGetter(Element.prototype, "scrollHeight");
|
|
121393
|
+
const getClientHeight = protoGetter(Element.prototype, "clientHeight");
|
|
121394
|
+
const getScrollWidth = protoGetter(Element.prototype, "scrollWidth");
|
|
121395
|
+
const getClientWidth = protoGetter(Element.prototype, "clientWidth");
|
|
121396
|
+
const getAttr = Element.prototype.getAttribute;
|
|
121397
|
+
const hasAttr = Element.prototype.hasAttribute;
|
|
121398
|
+
const getBCR = Element.prototype.getBoundingClientRect;
|
|
121399
|
+
|
|
121369
121400
|
function nodeRole(el) {
|
|
121370
|
-
const r =
|
|
121401
|
+
const r = getAttr.call(el, "role");
|
|
121371
121402
|
if (r) return r;
|
|
121372
|
-
const t = el.
|
|
121403
|
+
const t = getTagName.call(el).toLowerCase();
|
|
121373
121404
|
return t;
|
|
121374
121405
|
}
|
|
121375
121406
|
|
|
121376
121407
|
function accessibleName(el) {
|
|
121377
|
-
const aria =
|
|
121408
|
+
const aria = getAttr.call(el, "aria-label");
|
|
121378
121409
|
if (aria) return aria.trim().slice(0, 200);
|
|
121379
|
-
const labelledBy =
|
|
121410
|
+
const labelledBy = getAttr.call(el, "aria-labelledby");
|
|
121380
121411
|
if (labelledBy) {
|
|
121381
121412
|
const ids = labelledBy.split(/\\s+/);
|
|
121382
121413
|
const parts = [];
|
|
121383
121414
|
for (const id of ids) {
|
|
121384
121415
|
const ref = document.getElementById(id);
|
|
121385
|
-
|
|
121416
|
+
// getTextContent via the prototype: an aria-labelledby target can be a <form>
|
|
121417
|
+
// with a control named "textContent", which would shadow the inherited getter
|
|
121418
|
+
// to a control element and crash (.trim() on a non-string).
|
|
121419
|
+
if (ref) parts.push((getTextContent.call(ref) || "").trim());
|
|
121386
121420
|
}
|
|
121387
121421
|
if (parts.length) return parts.join(" ").slice(0, 200);
|
|
121388
121422
|
}
|
|
@@ -121391,36 +121425,44 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121391
121425
|
if (el.value) return el.value.slice(0, 200);
|
|
121392
121426
|
}
|
|
121393
121427
|
if (el instanceof HTMLImageElement && el.alt) return el.alt.slice(0, 200);
|
|
121394
|
-
|
|
121428
|
+
// getAttribute, not el.title: a <form> with a control named "title" clobbers the
|
|
121429
|
+
// .title property to return that element (not a string), and .slice() then throws,
|
|
121430
|
+
// aborting the whole describe. getAttribute always yields string | null.
|
|
121431
|
+
const t = getAttr.call(el, "title");
|
|
121395
121432
|
if (t) return t.slice(0, 200);
|
|
121396
121433
|
return null;
|
|
121397
121434
|
}
|
|
121398
121435
|
|
|
121399
121436
|
function ownText(el) {
|
|
121400
121437
|
let s = "";
|
|
121401
|
-
for (const child of el
|
|
121402
|
-
|
|
121438
|
+
for (const child of getChildNodes.call(el)) {
|
|
121439
|
+
// nodeType/nodeValue via the prototype getters, keeping the "every inherited
|
|
121440
|
+
// read goes through a captured getter" invariant whole: a child can be a
|
|
121441
|
+
// clobbering <form> whose named control shadows these to a control element.
|
|
121442
|
+
// (=== 3 already made a clobbered nodeType safe; this removes the lone
|
|
121443
|
+
// directly-read member so no read's safety rests on the comparison semantics.)
|
|
121444
|
+
if (getNodeType.call(child) === 3) s += getNodeValue.call(child);
|
|
121403
121445
|
}
|
|
121404
121446
|
return s.replace(/\\s+/g, " ").trim();
|
|
121405
121447
|
}
|
|
121406
121448
|
|
|
121407
121449
|
function isInteractive(el) {
|
|
121408
|
-
const tag = el.
|
|
121450
|
+
const tag = getTagName.call(el).toLowerCase();
|
|
121409
121451
|
if (tag === "a" && el.href) return true;
|
|
121410
121452
|
if (tag === "button") return true;
|
|
121411
121453
|
if (tag === "input" || tag === "textarea" || tag === "select") return true;
|
|
121412
121454
|
if (tag === "summary" || tag === "details") return true;
|
|
121413
|
-
if (
|
|
121414
|
-
const role =
|
|
121455
|
+
if (hasAttr.call(el, "onclick")) return true;
|
|
121456
|
+
const role = getAttr.call(el, "role");
|
|
121415
121457
|
if (role && /^(button|link|tab|menuitem|checkbox|radio|switch|option)$/i.test(role)) return true;
|
|
121416
|
-
const tabIndex =
|
|
121458
|
+
const tabIndex = getAttr.call(el, "tabindex");
|
|
121417
121459
|
if (tabIndex !== null && tabIndex !== "-1") return true;
|
|
121418
121460
|
return false;
|
|
121419
121461
|
}
|
|
121420
121462
|
|
|
121421
121463
|
function isDisabled(el) {
|
|
121422
|
-
if (
|
|
121423
|
-
if (
|
|
121464
|
+
if (hasAttr.call(el, "disabled")) return true;
|
|
121465
|
+
if (getAttr.call(el, "aria-disabled") === "true") return true;
|
|
121424
121466
|
return false;
|
|
121425
121467
|
}
|
|
121426
121468
|
|
|
@@ -121428,7 +121470,7 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121428
121470
|
if (el instanceof HTMLInputElement && (el.type === "checkbox" || el.type === "radio")) {
|
|
121429
121471
|
return el.checked;
|
|
121430
121472
|
}
|
|
121431
|
-
const v =
|
|
121473
|
+
const v = getAttr.call(el, "aria-checked");
|
|
121432
121474
|
if (v === "true") return true;
|
|
121433
121475
|
return false;
|
|
121434
121476
|
}
|
|
@@ -121442,13 +121484,16 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121442
121484
|
const oy = style.overflowY;
|
|
121443
121485
|
const ox = style.overflowX;
|
|
121444
121486
|
if (oy === "auto" || oy === "scroll" || ox === "auto" || ox === "scroll") {
|
|
121445
|
-
if (
|
|
121487
|
+
if (
|
|
121488
|
+
getScrollHeight.call(el) > getClientHeight.call(el) ||
|
|
121489
|
+
getScrollWidth.call(el) > getClientWidth.call(el)
|
|
121490
|
+
)
|
|
121491
|
+
return true;
|
|
121446
121492
|
}
|
|
121447
121493
|
return false;
|
|
121448
121494
|
}
|
|
121449
121495
|
|
|
121450
|
-
function
|
|
121451
|
-
const r = el.getBoundingClientRect();
|
|
121496
|
+
function normRect(r) {
|
|
121452
121497
|
const x = Math.max(0, Math.min(1, r.left / w));
|
|
121453
121498
|
const y = Math.max(0, Math.min(1, r.top / h));
|
|
121454
121499
|
const right = Math.max(0, Math.min(1, r.right / w));
|
|
@@ -121456,29 +121501,120 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121456
121501
|
return { x, y, width: Math.max(0, right - x), height: Math.max(0, bottom - y) };
|
|
121457
121502
|
}
|
|
121458
121503
|
|
|
121459
|
-
function
|
|
121460
|
-
|
|
121461
|
-
|
|
121462
|
-
|
|
121463
|
-
|
|
121464
|
-
|
|
121504
|
+
function frame(el) {
|
|
121505
|
+
return normRect(getBCR.call(el));
|
|
121506
|
+
}
|
|
121507
|
+
|
|
121508
|
+
// Painted extent of an element's own inline TEXT. A box-less element (display:contents,
|
|
121509
|
+
// or a zero-width box whose text overflows) has a 0x0 border box yet its text still
|
|
121510
|
+
// paints; a Range over its own text measures that. Measure ONLY the element's direct
|
|
121511
|
+
// text-node children \u2014 NOT selectNodeContents(el) over the whole subtree, which also
|
|
121512
|
+
// spans the still-laid-out boxes of visibility:hidden / opacity:0 element descendants
|
|
121513
|
+
// (they keep a layout box but paint nothing), oversizing the frame and mis-placing the
|
|
121514
|
+
// tap point. Returns 0x0 when an ancestor transform (e.g. scale(0)) or display:none
|
|
121515
|
+
// collapses the paint. walk() consults this only when the element has its own text.
|
|
121516
|
+
function contentFrame(el) {
|
|
121517
|
+
try {
|
|
121518
|
+
let box = null;
|
|
121519
|
+
for (const child of getChildNodes.call(el)) {
|
|
121520
|
+
// nodeType via the prototype getter (clobber-safe, like ownText); own text only.
|
|
121521
|
+
if (getNodeType.call(child) !== 3) continue;
|
|
121522
|
+
const range = document.createRange();
|
|
121523
|
+
range.selectNodeContents(child);
|
|
121524
|
+
const r = range.getBoundingClientRect();
|
|
121525
|
+
if (r.width <= 0 || r.height <= 0) continue;
|
|
121526
|
+
if (!box) {
|
|
121527
|
+
box = { left: r.left, top: r.top, right: r.right, bottom: r.bottom };
|
|
121528
|
+
} else {
|
|
121529
|
+
if (r.left < box.left) box.left = r.left;
|
|
121530
|
+
if (r.top < box.top) box.top = r.top;
|
|
121531
|
+
if (r.right > box.right) box.right = r.right;
|
|
121532
|
+
if (r.bottom > box.bottom) box.bottom = r.bottom;
|
|
121533
|
+
}
|
|
121534
|
+
}
|
|
121535
|
+
if (!box || box.right <= box.left || box.bottom <= box.top) return null;
|
|
121536
|
+
return normRect(box);
|
|
121537
|
+
} catch (e) {
|
|
121538
|
+
return null;
|
|
121465
121539
|
}
|
|
121466
|
-
|
|
121540
|
+
}
|
|
121541
|
+
|
|
121542
|
+
function overflowClips(style) {
|
|
121543
|
+
return style.overflowX !== "visible" || style.overflowY !== "visible";
|
|
121544
|
+
}
|
|
121545
|
+
|
|
121546
|
+
// An element has no box of its own when it is display:contents (renders children
|
|
121547
|
+
// but generates no box) or its border box is zero-area. We give such elements a
|
|
121548
|
+
// frame spanning their children rather than their own 0x0 rect.
|
|
121549
|
+
function boxless(el, style) {
|
|
121550
|
+
if (style.display === "contents") return true;
|
|
121551
|
+
const r = getBCR.call(el);
|
|
121552
|
+
return r.width <= 0 || r.height <= 0;
|
|
121553
|
+
}
|
|
121554
|
+
|
|
121555
|
+
function hidden(el, style) {
|
|
121556
|
+
if (style.display === "none") return true;
|
|
121557
|
+
// display:contents has no box, so box-only properties don't apply \u2014 it lays
|
|
121558
|
+
// its children out normally. Never prune it for opacity:0 (opacity affects a
|
|
121559
|
+
// box, of which there is none, so descendants still paint) or for its 0x0
|
|
121560
|
+
// rect; walk() descends and promotes the visible content.
|
|
121561
|
+
if (style.display === "contents") return false;
|
|
121562
|
+
if (style.opacity === "0") return true;
|
|
121563
|
+
// visibility:hidden is deliberately NOT hard-pruned here: visibility inherits but a
|
|
121564
|
+
// descendant can override it back to visible, so cutting the subtree would drop
|
|
121565
|
+
// painted content. walk() descends and suppresses only this element's own paint
|
|
121566
|
+
// (see \`invisibleSelf\`), pruning it only if no visible descendant survives.
|
|
121567
|
+
const r = getBCR.call(el);
|
|
121568
|
+
if (r.width > 0 && r.height > 0) return false;
|
|
121569
|
+
// Zero-area box: prune it only when it clips its overflow (a collapsed
|
|
121570
|
+
// overflow:hidden container genuinely hides its content). With the default
|
|
121571
|
+
// overflow:visible, abs-positioned / overflowing / floated descendants still
|
|
121572
|
+
// paint, so walk() must descend and promote them instead of cutting the subtree.
|
|
121573
|
+
return overflowClips(style);
|
|
121574
|
+
}
|
|
121575
|
+
|
|
121576
|
+
// Smallest normalized box covering every surviving child frame \u2014 the frame we give
|
|
121577
|
+
// a box-less wrapper we still emit, since it has no rect of its own.
|
|
121578
|
+
function unionFrame(children) {
|
|
121579
|
+
let minX = 1;
|
|
121580
|
+
let minY = 1;
|
|
121581
|
+
let maxRight = 0;
|
|
121582
|
+
let maxBottom = 0;
|
|
121583
|
+
for (const c of children) {
|
|
121584
|
+
minX = Math.min(minX, c.frame.x);
|
|
121585
|
+
minY = Math.min(minY, c.frame.y);
|
|
121586
|
+
maxRight = Math.max(maxRight, c.frame.x + c.frame.width);
|
|
121587
|
+
maxBottom = Math.max(maxBottom, c.frame.y + c.frame.height);
|
|
121588
|
+
}
|
|
121589
|
+
if (maxRight <= minX || maxBottom <= minY) {
|
|
121590
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
121591
|
+
}
|
|
121592
|
+
return { x: minX, y: minY, width: maxRight - minX, height: maxBottom - minY };
|
|
121467
121593
|
}
|
|
121468
121594
|
|
|
121469
121595
|
function walk(el, depth) {
|
|
121470
121596
|
if (truncated) return null;
|
|
121471
121597
|
if (depth > MAX_DEPTH) return null;
|
|
121472
121598
|
if (!(el instanceof Element)) return null;
|
|
121473
|
-
|
|
121474
|
-
if (
|
|
121475
|
-
|
|
121476
|
-
|
|
121599
|
+
const style = window.getComputedStyle(el);
|
|
121600
|
+
if (hidden(el, style)) return null;
|
|
121601
|
+
// Charge the node budget only for elements that can actually EMIT. A
|
|
121602
|
+
// visibility:hidden element paints nothing itself and is descended into
|
|
121603
|
+
// purely to catch a descendant that overrides visibility back to visible
|
|
121604
|
+
// (see hidden()); it is otherwise promoted/dropped. Counting it would let a
|
|
121605
|
+
// large fully-hidden subtree (a closed drawer/modal) exhaust the budget and
|
|
121606
|
+
// truncate genuinely visible content elsewhere in the tree. Its visible
|
|
121607
|
+
// descendants, if any, still consume the budget themselves.
|
|
121608
|
+
if (style.visibility !== "hidden") {
|
|
121609
|
+
if (nodeBudget <= 0) {
|
|
121610
|
+
truncated = true;
|
|
121611
|
+
return null;
|
|
121612
|
+
}
|
|
121613
|
+
nodeBudget--;
|
|
121477
121614
|
}
|
|
121478
|
-
nodeBudget--;
|
|
121479
121615
|
|
|
121480
121616
|
const childResults = [];
|
|
121481
|
-
for (const child of el
|
|
121617
|
+
for (const child of getChildrenEls.call(el)) {
|
|
121482
121618
|
const c = walk(child, depth + 1);
|
|
121483
121619
|
if (c) childResults.push(c);
|
|
121484
121620
|
}
|
|
@@ -121487,8 +121623,13 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121487
121623
|
// Web-components-heavy apps (VS Code, every Lit/Polymer SPA) put their
|
|
121488
121624
|
// interactive content under .shadowRoot, so without this descent describe
|
|
121489
121625
|
// returns an empty body.
|
|
121490
|
-
|
|
121491
|
-
|
|
121626
|
+
// getShadowRoot via the prototype: a <form> with a control named "shadowRoot"
|
|
121627
|
+
// would otherwise return that control, and we'd re-walk its light-DOM children as
|
|
121628
|
+
// shadow content and duplicate the subtree. A real ShadowRoot is a DocumentFragment
|
|
121629
|
+
// (never a form), so its own .children read is safe.
|
|
121630
|
+
const shadow = getShadowRoot.call(el);
|
|
121631
|
+
if (shadow) {
|
|
121632
|
+
for (const child of shadow.children) {
|
|
121492
121633
|
const c = walk(child, depth + 1);
|
|
121493
121634
|
if (c) childResults.push(c);
|
|
121494
121635
|
}
|
|
@@ -121497,7 +121638,7 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121497
121638
|
// Same-origin iframes: pierce contentDocument if accessible. Cross-origin
|
|
121498
121639
|
// contentDocument access throws SecurityError \u2014 swallowed silently so the
|
|
121499
121640
|
// walker doesn't abort the whole tree.
|
|
121500
|
-
if (el
|
|
121641
|
+
if (getTagName.call(el) === "IFRAME") {
|
|
121501
121642
|
try {
|
|
121502
121643
|
const doc = el.contentDocument;
|
|
121503
121644
|
if (doc && doc.documentElement) {
|
|
@@ -121509,30 +121650,89 @@ var DESCRIBE_DOM_SCRIPT = `(() => {
|
|
|
121509
121650
|
}
|
|
121510
121651
|
}
|
|
121511
121652
|
|
|
121512
|
-
|
|
121513
|
-
|
|
121514
|
-
|
|
121653
|
+
// A visibility:hidden element paints nothing itself, but a descendant can override
|
|
121654
|
+
// visibility back to visible, so walk() descended instead of pruning (see hidden()).
|
|
121655
|
+
// Suppress this element's own paint \u2014 its text / name / interactivity are invisible \u2014
|
|
121656
|
+
// and treat it as box-less so it contributes no box of its own: it survives only
|
|
121657
|
+
// through, and is framed by, whatever visible descendants it has.
|
|
121658
|
+
const invisibleSelf = style.visibility === "hidden";
|
|
121659
|
+
const text = invisibleSelf ? "" : ownText(el);
|
|
121660
|
+
const name = invisibleSelf ? null : accessibleName(el);
|
|
121661
|
+
const clickable = invisibleSelf ? false : isInteractive(el);
|
|
121515
121662
|
const role = nodeRole(el);
|
|
121663
|
+
// getAttribute, not el.id: like .title, a named form control can clobber the .id
|
|
121664
|
+
// property to a DOM node, which would then break JSON.stringify of the tree.
|
|
121665
|
+
// Computed here (before promotion) because an id / data-testid is agent-visible
|
|
121666
|
+
// targeting info: a wrapper that carries one is not a pure layer, so neither
|
|
121667
|
+
// promotion path below may drop it.
|
|
121668
|
+
const id =
|
|
121669
|
+
getAttr.call(el, "id") ||
|
|
121670
|
+
getAttr.call(el, "data-testid") ||
|
|
121671
|
+
getAttr.call(el, "data-test-id");
|
|
121672
|
+
const bl = invisibleSelf || boxless(el, style);
|
|
121673
|
+
|
|
121674
|
+
// A box-less element has no rect of its own. Its visible extent is whatever its
|
|
121675
|
+
// children span; with no surviving child, fall back to the painted extent of its own
|
|
121676
|
+
// inline TEXT \u2014 but only when it has its own text. A Range over a wrapper whose
|
|
121677
|
+
// element children were all pruned as invisible still measures their
|
|
121678
|
+
// visibility:hidden / opacity:0 layout boxes (non-zero though nothing paints), which
|
|
121679
|
+
// would resurrect an empty wrapper with a real frame; own text is the only inline
|
|
121680
|
+
// content not already represented by childResults. If the frame is still zero-area it
|
|
121681
|
+
// paints nothing \u2014 e.g. a transform: scale(0) subtree, whose descendants all collapse
|
|
121682
|
+
// \u2014 so it is invisible and dropped. A box-less wrapper with one child and nothing of
|
|
121683
|
+
// its own (no clickable / name / text / identifier) is just a layer, so promote the
|
|
121684
|
+
// child. (Clickable / named / identified box-less nodes fall through and are emitted
|
|
121685
|
+
// with this child- or content-spanning frame.)
|
|
121686
|
+
let selfFrame;
|
|
121687
|
+
if (bl) {
|
|
121688
|
+
selfFrame = unionFrame(childResults);
|
|
121689
|
+
if (text && selfFrame.width <= 0 && selfFrame.height <= 0) {
|
|
121690
|
+
const cf = contentFrame(el);
|
|
121691
|
+
if (cf) selfFrame = cf;
|
|
121692
|
+
}
|
|
121693
|
+
if (childResults.length === 0 && selfFrame.width <= 0 && selfFrame.height <= 0) {
|
|
121694
|
+
return null;
|
|
121695
|
+
}
|
|
121696
|
+
if (
|
|
121697
|
+
!clickable &&
|
|
121698
|
+
!name &&
|
|
121699
|
+
!text &&
|
|
121700
|
+
!id &&
|
|
121701
|
+
childResults.length === 1 &&
|
|
121702
|
+
(role === "div" || invisibleSelf)
|
|
121703
|
+
) {
|
|
121704
|
+
// Only a pure layout wrapper (a plain div, e.g. a display:contents RNW
|
|
121705
|
+
// wrapper) or a visibility:hidden element with no meaningful paint of
|
|
121706
|
+
// its own is promoted away. A box-less element with a SEMANTIC role
|
|
121707
|
+
// (list, nav, section, listitem, ...) is kept so its role isn't lost \u2014
|
|
121708
|
+
// mirroring the role === "div" gate on the boxed structural collapse
|
|
121709
|
+
// below.
|
|
121710
|
+
return childResults[0];
|
|
121711
|
+
}
|
|
121712
|
+
} else {
|
|
121713
|
+
selfFrame = frame(el);
|
|
121714
|
+
}
|
|
121715
|
+
|
|
121516
121716
|
// Prune structural wrappers with no info that just add a layer.
|
|
121517
|
-
// Keep them if they're roots/clickable/named/have text.
|
|
121717
|
+
// Keep them if they're roots/clickable/named/identified/have text.
|
|
121518
121718
|
if (
|
|
121519
121719
|
depth > 0 &&
|
|
121520
121720
|
childResults.length === 1 &&
|
|
121521
121721
|
!clickable &&
|
|
121522
121722
|
!name &&
|
|
121523
121723
|
!text &&
|
|
121724
|
+
!id &&
|
|
121524
121725
|
role === "div"
|
|
121525
121726
|
) {
|
|
121526
121727
|
return childResults[0];
|
|
121527
121728
|
}
|
|
121528
121729
|
const node = {
|
|
121529
121730
|
role,
|
|
121530
|
-
frame:
|
|
121731
|
+
frame: selfFrame,
|
|
121531
121732
|
children: childResults,
|
|
121532
121733
|
};
|
|
121533
121734
|
if (name) node.label = name;
|
|
121534
121735
|
if (text && text !== name) node.value = text.slice(0, 200);
|
|
121535
|
-
const id = el.id || el.getAttribute("data-testid") || el.getAttribute("data-test-id");
|
|
121536
121736
|
if (id) node.identifier = id;
|
|
121537
121737
|
if (clickable) node.clickable = true;
|
|
121538
121738
|
if (isDisabled(el)) node.disabled = true;
|
|
@@ -121579,13 +121779,15 @@ async function describeChromium(api) {
|
|
|
121579
121779
|
if (!parsed.tree) {
|
|
121580
121780
|
throw new Error("Chromium describe: empty tree");
|
|
121581
121781
|
}
|
|
121782
|
+
const data = { tree: parsed.tree, source: "cdp-dom" };
|
|
121582
121783
|
if (parsed.truncated) {
|
|
121583
121784
|
process.stderr.write(
|
|
121584
121785
|
`[chromium-describe] tree truncated at MAX_NODES \u2014 page exceeds the walker's budget; consider scoping the inspection.
|
|
121585
121786
|
`
|
|
121586
121787
|
);
|
|
121788
|
+
data.hint = "describe hit the node budget (MAX_NODES) and returned a PARTIAL tree \u2014 some on-screen content is missing. Scope the inspection to a smaller region (scroll to or focus the relevant view) and describe again.";
|
|
121587
121789
|
}
|
|
121588
|
-
return
|
|
121790
|
+
return data;
|
|
121589
121791
|
}
|
|
121590
121792
|
|
|
121591
121793
|
// ../tool-server/src/tools/await-ui-element/index.ts
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|