@browserbasehq/stagehand 3.0.7-alpha-4d71162beb119635b69b17637564a2bbd0e373e7 → 3.0.7-alpha-c6328376f19a9778d435980a992855e2b3bc6806
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/index.js +1270 -1132
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -179,7 +179,7 @@ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")])
|
|
|
179
179
|
var STAGEHAND_VERSION;
|
|
180
180
|
var init_version = __esm({
|
|
181
181
|
"lib/version.ts"() {
|
|
182
|
-
STAGEHAND_VERSION = "3.0.7-alpha-
|
|
182
|
+
STAGEHAND_VERSION = "3.0.7-alpha-c6328376f19a9778d435980a992855e2b3bc6806";
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
|
|
@@ -638,39 +638,6 @@ var init_executionContextRegistry = __esm({
|
|
|
638
638
|
}
|
|
639
639
|
});
|
|
640
640
|
|
|
641
|
-
// lib/v3/dom/build/a11yScripts.generated.ts
|
|
642
|
-
var a11yScriptBootstrap, a11yScriptSources, a11yScriptGlobalRefs;
|
|
643
|
-
var init_a11yScripts_generated = __esm({
|
|
644
|
-
"lib/v3/dom/build/a11yScripts.generated.ts"() {
|
|
645
|
-
a11yScriptBootstrap = 'if (!globalThis.__stagehandA11yScripts) { var __stagehandA11yScriptsFactory=(()=>{var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var N=(o,t)=>{for(var n in t)i(o,n,{get:t[n],enumerable:!0})},h=(o,t,n,d)=>{if(t&&typeof t=="object"||typeof t=="function")for(let u of f(t))!p.call(o,u)&&u!==n&&i(o,u,{get:()=>t[u],enumerable:!(d=a(t,u))||d.enumerable});return o};var E=o=>h(i({},"__esModule",{value:!0}),o);var b={};N(b,{documentHasFocusStrict:()=>g,getBoundingRectLite:()=>w,getScrollOffsets:()=>y,nodeToAbsoluteXPath:()=>$,resolveDeepActiveElement:()=>T});function y(){try{let o=window.scrollX??window.pageXOffset??document.documentElement?.scrollLeft??0,t=window.scrollY??window.pageYOffset??document.documentElement?.scrollTop??0;return{sx:Number(o)||0,sy:Number(t)||0}}catch{return{sx:0,sy:0}}}function w(){try{let o=this.getBoundingClientRect();return{left:Number(o?.left??0)||0,top:Number(o?.top??0)||0}}catch{return{left:0,top:0}}}function T(){try{return(t=>{let n=t.activeElement??null;for(;n&&n.shadowRoot&&n.shadowRoot.activeElement;)n=n.shadowRoot.activeElement;return n??null})(document)}catch{return null}}function $(){return(t=>{try{let n=e=>{if(!e||!e.parentNode)return 1;let l=1,m=`${e.nodeType}:${(e.nodeName||"").toLowerCase()}`;for(let c=e.previousSibling;c;c=c.previousSibling)`${c.nodeType}:${(c.nodeName||"").toLowerCase()}`===m&&(l+=1);return l},d=e=>{if(!e||e.nodeType===Node.DOCUMENT_NODE)return"";if(e.nodeType===Node.DOCUMENT_FRAGMENT_NODE)return"//";if(e.nodeType===Node.TEXT_NODE)return`text()[${n(e)}]`;if(e.nodeType===Node.COMMENT_NODE)return`comment()[${n(e)}]`;let l=(e.nodeName||"").toLowerCase();return`${l.includes(":")?`*[name()=\'${l}\']`:l}[${n(e)}]`},u=[],s=t;for(;s;){if(s.nodeType===Node.DOCUMENT_FRAGMENT_NODE){u.push("//"),s=s.host??null;continue}let e=d(s);e&&u.push(e),s=s.parentNode}u.reverse();let r="";for(let e of u)e==="//"?r=r?r.endsWith("/")?`${r}/`:`${r}//`:"//":r=r?r.endsWith("/")?`${r}${e}`:`${r}/${e}`:`/${e}`;return r||"/"}catch{return"/"}})(this)}function g(){try{return document.hasFocus()===!0}catch{return!1}}return E(b);})();\n globalThis.__stagehandA11yScripts = __stagehandA11yScriptsFactory;\n}';
|
|
646
|
-
a11yScriptSources = {
|
|
647
|
-
"documentHasFocusStrict": "function h(){try{return document.hasFocus()===!0}catch{return!1}}",
|
|
648
|
-
"getBoundingRectLite": "function f(){try{let r=this.getBoundingClientRect();return{left:Number(r?.left??0)||0,top:Number(r?.top??0)||0}}catch{return{left:0,top:0}}}",
|
|
649
|
-
"getScrollOffsets": "function a(){try{let r=window.scrollX??window.pageXOffset??document.documentElement?.scrollLeft??0,s=window.scrollY??window.pageYOffset??document.documentElement?.scrollTop??0;return{sx:Number(r)||0,sy:Number(s)||0}}catch{return{sx:0,sy:0}}}",
|
|
650
|
-
"nodeToAbsoluteXPath": 'function N(){return(s=>{try{let n=e=>{if(!e||!e.parentNode)return 1;let u=1,d=`${e.nodeType}:${(e.nodeName||"").toLowerCase()}`;for(let l=e.previousSibling;l;l=l.previousSibling)`${l.nodeType}:${(l.nodeName||"").toLowerCase()}`===d&&(u+=1);return u},i=e=>{if(!e||e.nodeType===Node.DOCUMENT_NODE)return"";if(e.nodeType===Node.DOCUMENT_FRAGMENT_NODE)return"//";if(e.nodeType===Node.TEXT_NODE)return`text()[${n(e)}]`;if(e.nodeType===Node.COMMENT_NODE)return`comment()[${n(e)}]`;let u=(e.nodeName||"").toLowerCase();return`${u.includes(":")?`*[name()=\'${u}\']`:u}[${n(e)}]`},c=[],o=s;for(;o;){if(o.nodeType===Node.DOCUMENT_FRAGMENT_NODE){c.push("//"),o=o.host??null;continue}let e=i(o);e&&c.push(e),o=o.parentNode}c.reverse();let t="";for(let e of c)e==="//"?t=t?t.endsWith("/")?`${t}/`:`${t}//`:"//":t=t?t.endsWith("/")?`${t}${e}`:`${t}/${e}`:`/${e}`;return t||"/"}catch{return"/"}})(this)}',
|
|
651
|
-
"resolveDeepActiveElement": "function p(){try{return(s=>{let n=s.activeElement??null;for(;n&&n.shadowRoot&&n.shadowRoot.activeElement;)n=n.shadowRoot.activeElement;return n??null})(document)}catch{return null}}"
|
|
652
|
-
};
|
|
653
|
-
a11yScriptGlobalRefs = {
|
|
654
|
-
"documentHasFocusStrict": "globalThis.__stagehandA11yScripts.documentHasFocusStrict",
|
|
655
|
-
"getBoundingRectLite": "globalThis.__stagehandA11yScripts.getBoundingRectLite",
|
|
656
|
-
"getScrollOffsets": "globalThis.__stagehandA11yScripts.getScrollOffsets",
|
|
657
|
-
"nodeToAbsoluteXPath": "globalThis.__stagehandA11yScripts.nodeToAbsoluteXPath",
|
|
658
|
-
"resolveDeepActiveElement": "globalThis.__stagehandA11yScripts.resolveDeepActiveElement"
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
// lib/v3/understudy/a11yInvocation.ts
|
|
664
|
-
function buildA11yInvocation(name, args) {
|
|
665
|
-
const invocation = `${a11yScriptGlobalRefs[name]}(${args.join(", ")})`;
|
|
666
|
-
return `(() => { ${a11yScriptBootstrap}; return ${invocation}; })()`;
|
|
667
|
-
}
|
|
668
|
-
var init_a11yInvocation = __esm({
|
|
669
|
-
"lib/v3/understudy/a11yInvocation.ts"() {
|
|
670
|
-
init_a11yScripts_generated();
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
|
|
674
641
|
// lib/v3/dom/build/locatorScripts.generated.ts
|
|
675
642
|
var locatorScriptBootstrap, locatorScriptSources, locatorScriptGlobalRefs;
|
|
676
643
|
var init_locatorScripts_generated = __esm({
|
|
@@ -738,252 +705,60 @@ var init_locatorInvocation = __esm({
|
|
|
738
705
|
}
|
|
739
706
|
});
|
|
740
707
|
|
|
741
|
-
// lib/v3/
|
|
742
|
-
|
|
708
|
+
// lib/v3/dom/build/a11yScripts.generated.ts
|
|
709
|
+
var a11yScriptBootstrap, a11yScriptSources, a11yScriptGlobalRefs;
|
|
710
|
+
var init_a11yScripts_generated = __esm({
|
|
711
|
+
"lib/v3/dom/build/a11yScripts.generated.ts"() {
|
|
712
|
+
a11yScriptBootstrap = 'if (!globalThis.__stagehandA11yScripts) { var __stagehandA11yScriptsFactory=(()=>{var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var N=(o,t)=>{for(var n in t)i(o,n,{get:t[n],enumerable:!0})},h=(o,t,n,d)=>{if(t&&typeof t=="object"||typeof t=="function")for(let u of f(t))!p.call(o,u)&&u!==n&&i(o,u,{get:()=>t[u],enumerable:!(d=a(t,u))||d.enumerable});return o};var E=o=>h(i({},"__esModule",{value:!0}),o);var b={};N(b,{documentHasFocusStrict:()=>g,getBoundingRectLite:()=>w,getScrollOffsets:()=>y,nodeToAbsoluteXPath:()=>$,resolveDeepActiveElement:()=>T});function y(){try{let o=window.scrollX??window.pageXOffset??document.documentElement?.scrollLeft??0,t=window.scrollY??window.pageYOffset??document.documentElement?.scrollTop??0;return{sx:Number(o)||0,sy:Number(t)||0}}catch{return{sx:0,sy:0}}}function w(){try{let o=this.getBoundingClientRect();return{left:Number(o?.left??0)||0,top:Number(o?.top??0)||0}}catch{return{left:0,top:0}}}function T(){try{return(t=>{let n=t.activeElement??null;for(;n&&n.shadowRoot&&n.shadowRoot.activeElement;)n=n.shadowRoot.activeElement;return n??null})(document)}catch{return null}}function $(){return(t=>{try{let n=e=>{if(!e||!e.parentNode)return 1;let l=1,m=`${e.nodeType}:${(e.nodeName||"").toLowerCase()}`;for(let c=e.previousSibling;c;c=c.previousSibling)`${c.nodeType}:${(c.nodeName||"").toLowerCase()}`===m&&(l+=1);return l},d=e=>{if(!e||e.nodeType===Node.DOCUMENT_NODE)return"";if(e.nodeType===Node.DOCUMENT_FRAGMENT_NODE)return"//";if(e.nodeType===Node.TEXT_NODE)return`text()[${n(e)}]`;if(e.nodeType===Node.COMMENT_NODE)return`comment()[${n(e)}]`;let l=(e.nodeName||"").toLowerCase();return`${l.includes(":")?`*[name()=\'${l}\']`:l}[${n(e)}]`},u=[],s=t;for(;s;){if(s.nodeType===Node.DOCUMENT_FRAGMENT_NODE){u.push("//"),s=s.host??null;continue}let e=d(s);e&&u.push(e),s=s.parentNode}u.reverse();let r="";for(let e of u)e==="//"?r=r?r.endsWith("/")?`${r}/`:`${r}//`:"//":r=r?r.endsWith("/")?`${r}${e}`:`${r}/${e}`:`/${e}`;return r||"/"}catch{return"/"}})(this)}function g(){try{return document.hasFocus()===!0}catch{return!1}}return E(b);})();\n globalThis.__stagehandA11yScripts = __stagehandA11yScriptsFactory;\n}';
|
|
713
|
+
a11yScriptSources = {
|
|
714
|
+
"documentHasFocusStrict": "function h(){try{return document.hasFocus()===!0}catch{return!1}}",
|
|
715
|
+
"getBoundingRectLite": "function f(){try{let r=this.getBoundingClientRect();return{left:Number(r?.left??0)||0,top:Number(r?.top??0)||0}}catch{return{left:0,top:0}}}",
|
|
716
|
+
"getScrollOffsets": "function a(){try{let r=window.scrollX??window.pageXOffset??document.documentElement?.scrollLeft??0,s=window.scrollY??window.pageYOffset??document.documentElement?.scrollTop??0;return{sx:Number(r)||0,sy:Number(s)||0}}catch{return{sx:0,sy:0}}}",
|
|
717
|
+
"nodeToAbsoluteXPath": 'function N(){return(s=>{try{let n=e=>{if(!e||!e.parentNode)return 1;let u=1,d=`${e.nodeType}:${(e.nodeName||"").toLowerCase()}`;for(let l=e.previousSibling;l;l=l.previousSibling)`${l.nodeType}:${(l.nodeName||"").toLowerCase()}`===d&&(u+=1);return u},i=e=>{if(!e||e.nodeType===Node.DOCUMENT_NODE)return"";if(e.nodeType===Node.DOCUMENT_FRAGMENT_NODE)return"//";if(e.nodeType===Node.TEXT_NODE)return`text()[${n(e)}]`;if(e.nodeType===Node.COMMENT_NODE)return`comment()[${n(e)}]`;let u=(e.nodeName||"").toLowerCase();return`${u.includes(":")?`*[name()=\'${u}\']`:u}[${n(e)}]`},c=[],o=s;for(;o;){if(o.nodeType===Node.DOCUMENT_FRAGMENT_NODE){c.push("//"),o=o.host??null;continue}let e=i(o);e&&c.push(e),o=o.parentNode}c.reverse();let t="";for(let e of c)e==="//"?t=t?t.endsWith("/")?`${t}/`:`${t}//`:"//":t=t?t.endsWith("/")?`${t}${e}`:`${t}/${e}`:`/${e}`;return t||"/"}catch{return"/"}})(this)}',
|
|
718
|
+
"resolveDeepActiveElement": "function p(){try{return(s=>{let n=s.activeElement??null;for(;n&&n.shadowRoot&&n.shadowRoot.activeElement;)n=n.shadowRoot.activeElement;return n??null})(document)}catch{return null}}"
|
|
719
|
+
};
|
|
720
|
+
a11yScriptGlobalRefs = {
|
|
721
|
+
"documentHasFocusStrict": "globalThis.__stagehandA11yScripts.documentHasFocusStrict",
|
|
722
|
+
"getBoundingRectLite": "globalThis.__stagehandA11yScripts.getBoundingRectLite",
|
|
723
|
+
"getScrollOffsets": "globalThis.__stagehandA11yScripts.getScrollOffsets",
|
|
724
|
+
"nodeToAbsoluteXPath": "globalThis.__stagehandA11yScripts.nodeToAbsoluteXPath",
|
|
725
|
+
"resolveDeepActiveElement": "globalThis.__stagehandA11yScripts.resolveDeepActiveElement"
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// lib/v3/understudy/a11y/snapshot/xpathUtils.ts
|
|
731
|
+
function buildAbsoluteXPathFromChain(chain, leafSession, leafBackendNodeId) {
|
|
743
732
|
return __async(this, null, function* () {
|
|
744
|
-
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
const iframeChain = [];
|
|
753
|
-
let curFrameId = page.mainFrameId();
|
|
754
|
-
let curSession = page.getSessionForFrame(curFrameId);
|
|
755
|
-
let curX = x2;
|
|
756
|
-
let curY = y;
|
|
757
|
-
for (let depth = 0; depth < 8; depth++) {
|
|
758
|
-
try {
|
|
759
|
-
yield curSession.send("DOM.enable").catch(() => {
|
|
760
|
-
});
|
|
761
|
-
let sx = 0;
|
|
762
|
-
let sy = 0;
|
|
763
|
-
try {
|
|
764
|
-
yield curSession.send("Runtime.enable").catch(() => {
|
|
765
|
-
});
|
|
766
|
-
const ctxId = yield executionContexts.waitForMainWorld(curSession, curFrameId).catch(() => {
|
|
767
|
-
});
|
|
768
|
-
const scrollExpr = buildA11yInvocation("getScrollOffsets", []);
|
|
769
|
-
const evalParams = ctxId ? {
|
|
770
|
-
contextId: ctxId,
|
|
771
|
-
expression: scrollExpr,
|
|
772
|
-
returnByValue: true
|
|
773
|
-
} : { expression: scrollExpr, returnByValue: true };
|
|
774
|
-
const { result } = yield curSession.send("Runtime.evaluate", evalParams);
|
|
775
|
-
sx = Number((_b = (_a4 = result == null ? void 0 : result.value) == null ? void 0 : _a4.sx) != null ? _b : 0);
|
|
776
|
-
sy = Number((_d2 = (_c = result == null ? void 0 : result.value) == null ? void 0 : _c.sy) != null ? _d2 : 0);
|
|
777
|
-
} catch (e2) {
|
|
778
|
-
}
|
|
779
|
-
const xi = Math.max(0, Math.floor(curX + sx));
|
|
780
|
-
const yi = Math.max(0, Math.floor(curY + sy));
|
|
781
|
-
let res;
|
|
782
|
-
try {
|
|
783
|
-
res = yield curSession.send("DOM.getNodeForLocation", {
|
|
784
|
-
x: xi,
|
|
785
|
-
y: yi,
|
|
786
|
-
includeUserAgentShadowDOM: false,
|
|
787
|
-
ignorePointerEventsNone: false
|
|
788
|
-
});
|
|
789
|
-
} catch (e2) {
|
|
790
|
-
return null;
|
|
791
|
-
}
|
|
792
|
-
const be = res == null ? void 0 : res.backendNodeId;
|
|
793
|
-
const reportedFrameId = res == null ? void 0 : res.frameId;
|
|
794
|
-
if (typeof be === "number" && reportedFrameId && reportedFrameId !== curFrameId) {
|
|
795
|
-
const abs = yield buildAbsoluteXPathFromChain(
|
|
796
|
-
iframeChain,
|
|
797
|
-
curSession,
|
|
798
|
-
be
|
|
799
|
-
);
|
|
800
|
-
return abs ? { frameId: reportedFrameId, backendNodeId: be, absoluteXPath: abs } : null;
|
|
801
|
-
}
|
|
802
|
-
if (typeof be !== "number") return null;
|
|
803
|
-
let matchedChild;
|
|
804
|
-
for (const fid of listChildrenOf(parentByFrame, curFrameId)) {
|
|
805
|
-
try {
|
|
806
|
-
const { backendNodeId } = yield curSession.send("DOM.getFrameOwner", { frameId: fid });
|
|
807
|
-
if (backendNodeId === be) {
|
|
808
|
-
matchedChild = fid;
|
|
809
|
-
break;
|
|
810
|
-
}
|
|
811
|
-
} catch (e2) {
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
if (!matchedChild) {
|
|
815
|
-
const abs = yield buildAbsoluteXPathFromChain(
|
|
816
|
-
iframeChain,
|
|
817
|
-
curSession,
|
|
818
|
-
be
|
|
819
|
-
);
|
|
820
|
-
return abs ? { frameId: curFrameId, backendNodeId: be, absoluteXPath: abs } : null;
|
|
821
|
-
}
|
|
822
|
-
iframeChain.push({
|
|
823
|
-
parentFrameId: curFrameId,
|
|
824
|
-
parentSession: curSession,
|
|
825
|
-
iframeBackendNodeId: be
|
|
826
|
-
});
|
|
827
|
-
let left = 0;
|
|
828
|
-
let top = 0;
|
|
829
|
-
try {
|
|
830
|
-
const { object } = yield curSession.send("DOM.resolveNode", { backendNodeId: be });
|
|
831
|
-
const objectId = object == null ? void 0 : object.objectId;
|
|
832
|
-
if (objectId) {
|
|
833
|
-
const { result } = yield curSession.send("Runtime.callFunctionOn", {
|
|
834
|
-
objectId,
|
|
835
|
-
functionDeclaration: a11yScriptSources.getBoundingRectLite,
|
|
836
|
-
returnByValue: true
|
|
837
|
-
});
|
|
838
|
-
left = Number((_f = (_e = result == null ? void 0 : result.value) == null ? void 0 : _e.left) != null ? _f : 0);
|
|
839
|
-
top = Number((_h = (_g = result == null ? void 0 : result.value) == null ? void 0 : _g.top) != null ? _h : 0);
|
|
840
|
-
yield curSession.send("Runtime.releaseObject", { objectId }).catch(() => {
|
|
841
|
-
});
|
|
842
|
-
}
|
|
843
|
-
} catch (e2) {
|
|
844
|
-
}
|
|
845
|
-
curX = Math.max(0, curX - left);
|
|
846
|
-
curY = Math.max(0, curY - top);
|
|
847
|
-
curFrameId = matchedChild;
|
|
848
|
-
curSession = page.getSessionForFrame(curFrameId);
|
|
849
|
-
} catch (e2) {
|
|
850
|
-
return null;
|
|
851
|
-
}
|
|
733
|
+
let prefix = "";
|
|
734
|
+
for (const step of chain) {
|
|
735
|
+
const xp = yield absoluteXPathForBackendNode(
|
|
736
|
+
step.parentSession,
|
|
737
|
+
step.iframeBackendNodeId
|
|
738
|
+
);
|
|
739
|
+
if (!xp) continue;
|
|
740
|
+
prefix = prefix ? prefixXPath(prefix, xp) : normalizeXPath(xp);
|
|
852
741
|
}
|
|
853
|
-
|
|
742
|
+
const leaf = yield absoluteXPathForBackendNode(
|
|
743
|
+
leafSession,
|
|
744
|
+
leafBackendNodeId
|
|
745
|
+
);
|
|
746
|
+
if (!leaf) return prefix || "/";
|
|
747
|
+
return prefix ? prefixXPath(prefix, leaf) : normalizeXPath(leaf);
|
|
854
748
|
});
|
|
855
749
|
}
|
|
856
|
-
function
|
|
750
|
+
function absoluteXPathForBackendNode(session, backendNodeId) {
|
|
857
751
|
return __async(this, null, function* () {
|
|
858
|
-
var _a4;
|
|
859
|
-
const tree = page.getFullFrameTree();
|
|
860
|
-
const parentByFrame = /* @__PURE__ */ new Map();
|
|
861
|
-
(function index(n, parent) {
|
|
862
|
-
var _a5;
|
|
863
|
-
parentByFrame.set(n.frame.id, parent);
|
|
864
|
-
for (const c of (_a5 = n.childFrames) != null ? _a5 : []) index(c, n.frame.id);
|
|
865
|
-
})(tree, null);
|
|
866
|
-
const frames = page.listAllFrameIds();
|
|
867
|
-
let focusedFrameId = null;
|
|
868
|
-
for (const fid of frames) {
|
|
869
|
-
const sess = page.getSessionForFrame(fid);
|
|
870
|
-
try {
|
|
871
|
-
yield sess.send("Runtime.enable").catch(() => {
|
|
872
|
-
});
|
|
873
|
-
const ctxId = yield executionContexts.waitForMainWorld(sess, fid, 1e3).catch(() => {
|
|
874
|
-
});
|
|
875
|
-
const hasFocusExpr = buildA11yInvocation("documentHasFocusStrict", []);
|
|
876
|
-
const evalParams = ctxId ? {
|
|
877
|
-
contextId: ctxId,
|
|
878
|
-
expression: hasFocusExpr,
|
|
879
|
-
returnByValue: true
|
|
880
|
-
} : { expression: hasFocusExpr, returnByValue: true };
|
|
881
|
-
const { result } = yield sess.send(
|
|
882
|
-
"Runtime.evaluate",
|
|
883
|
-
evalParams
|
|
884
|
-
);
|
|
885
|
-
if ((result == null ? void 0 : result.value) === true) {
|
|
886
|
-
focusedFrameId = fid;
|
|
887
|
-
break;
|
|
888
|
-
}
|
|
889
|
-
} catch (e2) {
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
if (!focusedFrameId) focusedFrameId = page.mainFrameId();
|
|
893
|
-
const focusedSession = page.getSessionForFrame(focusedFrameId);
|
|
894
|
-
let objectId;
|
|
895
752
|
try {
|
|
896
|
-
yield
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
});
|
|
900
|
-
const activeExpr = buildA11yInvocation("resolveDeepActiveElement", []);
|
|
901
|
-
const evalParams = ctxId ? {
|
|
902
|
-
contextId: ctxId,
|
|
903
|
-
expression: activeExpr,
|
|
904
|
-
returnByValue: false
|
|
905
|
-
} : { expression: activeExpr, returnByValue: false };
|
|
906
|
-
const { result } = yield focusedSession.send(
|
|
907
|
-
"Runtime.evaluate",
|
|
908
|
-
evalParams
|
|
753
|
+
const { object } = yield session.send(
|
|
754
|
+
"DOM.resolveNode",
|
|
755
|
+
{ backendNodeId }
|
|
909
756
|
);
|
|
910
|
-
objectId =
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
const leafXPath = yield (() => __async(null, null, function* () {
|
|
916
|
-
try {
|
|
917
|
-
const { result } = yield focusedSession.send("Runtime.callFunctionOn", {
|
|
918
|
-
objectId,
|
|
919
|
-
functionDeclaration: a11yScriptSources.nodeToAbsoluteXPath,
|
|
920
|
-
returnByValue: true
|
|
921
|
-
});
|
|
922
|
-
try {
|
|
923
|
-
yield focusedSession.send("Runtime.releaseObject", { objectId });
|
|
924
|
-
} catch (e2) {
|
|
925
|
-
}
|
|
926
|
-
const xp = (result == null ? void 0 : result.value) || "";
|
|
927
|
-
return typeof xp === "string" && xp ? xp : null;
|
|
928
|
-
} catch (e2) {
|
|
929
|
-
try {
|
|
930
|
-
yield focusedSession.send("Runtime.releaseObject", { objectId });
|
|
931
|
-
} catch (e3) {
|
|
932
|
-
}
|
|
933
|
-
return null;
|
|
934
|
-
}
|
|
935
|
-
}))();
|
|
936
|
-
if (!leafXPath) return null;
|
|
937
|
-
let prefix = "";
|
|
938
|
-
let cur = focusedFrameId;
|
|
939
|
-
while (cur) {
|
|
940
|
-
const parent = (_a4 = parentByFrame.get(cur)) != null ? _a4 : null;
|
|
941
|
-
if (!parent) break;
|
|
942
|
-
const parentSess = page.getSessionForFrame(parent);
|
|
943
|
-
try {
|
|
944
|
-
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: cur });
|
|
945
|
-
if (typeof backendNodeId === "number") {
|
|
946
|
-
const xp = yield absoluteXPathForBackendNode(parentSess, backendNodeId);
|
|
947
|
-
if (xp) prefix = prefix ? prefixXPath(prefix, xp) : normalizeXPath(xp);
|
|
948
|
-
}
|
|
949
|
-
} catch (e2) {
|
|
950
|
-
}
|
|
951
|
-
cur = parent;
|
|
952
|
-
}
|
|
953
|
-
return prefix ? prefixXPath(prefix, leafXPath) : normalizeXPath(leafXPath);
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
function buildAbsoluteXPathFromChain(chain, leafSession, leafBackendNodeId) {
|
|
957
|
-
return __async(this, null, function* () {
|
|
958
|
-
let prefix = "";
|
|
959
|
-
for (const step of chain) {
|
|
960
|
-
const xp = yield absoluteXPathForBackendNode(
|
|
961
|
-
step.parentSession,
|
|
962
|
-
step.iframeBackendNodeId
|
|
963
|
-
);
|
|
964
|
-
if (!xp) continue;
|
|
965
|
-
prefix = prefix ? prefixXPath(prefix, xp) : normalizeXPath(xp);
|
|
966
|
-
}
|
|
967
|
-
const leaf = yield absoluteXPathForBackendNode(
|
|
968
|
-
leafSession,
|
|
969
|
-
leafBackendNodeId
|
|
970
|
-
);
|
|
971
|
-
if (!leaf) return prefix || "/";
|
|
972
|
-
return prefix ? prefixXPath(prefix, leaf) : normalizeXPath(leaf);
|
|
973
|
-
});
|
|
974
|
-
}
|
|
975
|
-
function absoluteXPathForBackendNode(session, backendNodeId) {
|
|
976
|
-
return __async(this, null, function* () {
|
|
977
|
-
try {
|
|
978
|
-
const { object } = yield session.send(
|
|
979
|
-
"DOM.resolveNode",
|
|
980
|
-
{ backendNodeId }
|
|
981
|
-
);
|
|
982
|
-
const objectId = object == null ? void 0 : object.objectId;
|
|
983
|
-
if (!objectId) return null;
|
|
984
|
-
const { result } = yield session.send(
|
|
985
|
-
"Runtime.callFunctionOn",
|
|
986
|
-
{
|
|
757
|
+
const objectId = object == null ? void 0 : object.objectId;
|
|
758
|
+
if (!objectId) return null;
|
|
759
|
+
const { result } = yield session.send(
|
|
760
|
+
"Runtime.callFunctionOn",
|
|
761
|
+
{
|
|
987
762
|
objectId,
|
|
988
763
|
functionDeclaration: a11yScriptSources.nodeToAbsoluteXPath,
|
|
989
764
|
returnByValue: true
|
|
@@ -997,483 +772,168 @@ function absoluteXPathForBackendNode(session, backendNodeId) {
|
|
|
997
772
|
}
|
|
998
773
|
});
|
|
999
774
|
}
|
|
1000
|
-
function
|
|
1001
|
-
|
|
775
|
+
function prefixXPath(parentAbs, child) {
|
|
776
|
+
const p = parentAbs === "/" ? "" : parentAbs.replace(/\/$/, "");
|
|
777
|
+
if (!child || child === "/") return p || "/";
|
|
778
|
+
if (child.startsWith("//"))
|
|
779
|
+
return p ? `${p}//${child.slice(2)}` : `//${child.slice(2)}`;
|
|
780
|
+
const c = child.replace(/^\//, "");
|
|
781
|
+
return p ? `${p}/${c}` : `/${c}`;
|
|
1002
782
|
}
|
|
1003
|
-
function
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
783
|
+
function normalizeXPath(x2) {
|
|
784
|
+
if (!x2) return "";
|
|
785
|
+
let s2 = x2.trim().replace(/^xpath=/i, "");
|
|
786
|
+
if (!s2.startsWith("/")) s2 = "/" + s2;
|
|
787
|
+
if (s2.length > 1 && s2.endsWith("/")) s2 = s2.slice(0, -1);
|
|
788
|
+
return s2;
|
|
1008
789
|
}
|
|
1009
|
-
function
|
|
1010
|
-
var _a4
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
790
|
+
function buildChildXPathSegments(kids) {
|
|
791
|
+
var _a4;
|
|
792
|
+
const segs = [];
|
|
793
|
+
const ctr = {};
|
|
794
|
+
for (const child of kids) {
|
|
795
|
+
const tag = String(child.nodeName).toLowerCase();
|
|
796
|
+
const key = `${child.nodeType}:${tag}`;
|
|
797
|
+
const idx = ctr[key] = ((_a4 = ctr[key]) != null ? _a4 : 0) + 1;
|
|
798
|
+
if (child.nodeType === 3) {
|
|
799
|
+
segs.push(`text()[${idx}]`);
|
|
800
|
+
} else if (child.nodeType === 8) {
|
|
801
|
+
segs.push(`comment()[${idx}]`);
|
|
802
|
+
} else {
|
|
803
|
+
segs.push(
|
|
804
|
+
tag.includes(":") ? `*[name()='${tag}'][${idx}]` : `${tag}[${idx}]`
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return segs;
|
|
1015
809
|
}
|
|
1016
|
-
function
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
return
|
|
810
|
+
function joinXPath(base, step) {
|
|
811
|
+
if (step === "//") {
|
|
812
|
+
if (!base || base === "/") return "//";
|
|
813
|
+
return base.endsWith("/") ? `${base}/` : `${base}//`;
|
|
814
|
+
}
|
|
815
|
+
if (!base || base === "/") return step ? `/${step}` : "/";
|
|
816
|
+
if (base.endsWith("//")) return `${base}${step}`;
|
|
817
|
+
if (!step) return base;
|
|
818
|
+
return `${base}/${step}`;
|
|
1022
819
|
}
|
|
1023
|
-
|
|
820
|
+
var init_xpathUtils = __esm({
|
|
821
|
+
"lib/v3/understudy/a11y/snapshot/xpathUtils.ts"() {
|
|
822
|
+
init_a11yScripts_generated();
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
// lib/v3/understudy/a11y/snapshot/focusSelectors.ts
|
|
827
|
+
function parseXPathToSteps(path8) {
|
|
828
|
+
const s2 = path8.trim();
|
|
829
|
+
let i2 = 0;
|
|
830
|
+
const steps = [];
|
|
831
|
+
while (i2 < s2.length) {
|
|
832
|
+
let axis = "child";
|
|
833
|
+
if (s2.startsWith("//", i2)) {
|
|
834
|
+
axis = "desc";
|
|
835
|
+
i2 += 2;
|
|
836
|
+
} else if (s2[i2] === "/") {
|
|
837
|
+
axis = "child";
|
|
838
|
+
i2 += 1;
|
|
839
|
+
}
|
|
840
|
+
const start = i2;
|
|
841
|
+
while (i2 < s2.length && s2[i2] !== "/") i2++;
|
|
842
|
+
const raw = s2.slice(start, i2).trim();
|
|
843
|
+
if (!raw) continue;
|
|
844
|
+
const name = raw.replace(/\[\d+\]\s*$/u, "").toLowerCase();
|
|
845
|
+
steps.push({ axis, raw, name });
|
|
846
|
+
}
|
|
847
|
+
return steps;
|
|
848
|
+
}
|
|
849
|
+
function buildXPathFromSteps(steps) {
|
|
850
|
+
let out = "";
|
|
851
|
+
for (const st of steps) {
|
|
852
|
+
out += st.axis === "desc" ? "//" : "/";
|
|
853
|
+
out += st.raw;
|
|
854
|
+
}
|
|
855
|
+
return out || "/";
|
|
856
|
+
}
|
|
857
|
+
function resolveFocusFrameAndTail(page, absoluteXPath, parentByFrame, rootId) {
|
|
1024
858
|
return __async(this, null, function* () {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
859
|
+
const steps = parseXPathToSteps(absoluteXPath);
|
|
860
|
+
let ctxFrameId = rootId;
|
|
861
|
+
let buf = [];
|
|
862
|
+
let absPrefix = "";
|
|
863
|
+
const flushIntoChild = () => __async(null, null, function* () {
|
|
864
|
+
if (!buf.length) return;
|
|
865
|
+
const selectorForIframe = buildXPathFromSteps(buf);
|
|
866
|
+
const parentSess = page.getSessionForFrame(ctxFrameId);
|
|
867
|
+
const objectId = yield resolveObjectIdForXPath(
|
|
868
|
+
parentSess,
|
|
869
|
+
selectorForIframe,
|
|
870
|
+
ctxFrameId
|
|
871
|
+
);
|
|
872
|
+
if (!objectId)
|
|
873
|
+
throw new StagehandIframeError(
|
|
874
|
+
selectorForIframe,
|
|
875
|
+
"Failed to resolve iframe element by XPath"
|
|
876
|
+
);
|
|
877
|
+
try {
|
|
878
|
+
yield parentSess.send("DOM.enable").catch(() => {
|
|
879
|
+
});
|
|
880
|
+
const desc = yield parentSess.send(
|
|
881
|
+
"DOM.describeNode",
|
|
882
|
+
{ objectId }
|
|
883
|
+
);
|
|
884
|
+
const iframeBackendNodeId = desc.node.backendNodeId;
|
|
885
|
+
let childFrameId;
|
|
886
|
+
for (const fid of listChildrenOf(parentByFrame, ctxFrameId)) {
|
|
1043
887
|
try {
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
pierce
|
|
1049
|
-
})
|
|
1050
|
-
);
|
|
1051
|
-
mergeDomNodes(node, described.node);
|
|
1052
|
-
if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {
|
|
1053
|
-
node.nodeId = described.node.nodeId;
|
|
1054
|
-
expandedNodeIds.add(described.node.nodeId);
|
|
1055
|
-
}
|
|
1056
|
-
expanded = true;
|
|
1057
|
-
break;
|
|
1058
|
-
} catch (err) {
|
|
1059
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1060
|
-
if (isCborStackError(message)) {
|
|
1061
|
-
continue;
|
|
888
|
+
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: fid });
|
|
889
|
+
if (backendNodeId === iframeBackendNodeId) {
|
|
890
|
+
childFrameId = fid;
|
|
891
|
+
break;
|
|
1062
892
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
`Failed to expand DOM node ${identifier}: ${String(err)}`
|
|
1066
|
-
);
|
|
893
|
+
} catch (e2) {
|
|
894
|
+
continue;
|
|
1067
895
|
}
|
|
1068
896
|
}
|
|
1069
|
-
if (!
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
897
|
+
if (!childFrameId)
|
|
898
|
+
throw new StagehandIframeError(
|
|
899
|
+
selectorForIframe,
|
|
900
|
+
"Could not map iframe to child frameId"
|
|
1073
901
|
);
|
|
1074
|
-
|
|
902
|
+
absPrefix = prefixXPath(absPrefix || "/", selectorForIframe);
|
|
903
|
+
ctxFrameId = childFrameId;
|
|
904
|
+
} finally {
|
|
905
|
+
yield parentSess.send("Runtime.releaseObject", { objectId }).catch(() => {
|
|
906
|
+
});
|
|
1075
907
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
908
|
+
buf = [];
|
|
909
|
+
});
|
|
910
|
+
for (const st of steps) {
|
|
911
|
+
buf.push(st);
|
|
912
|
+
if (IFRAME_STEP_RE.test(st.name)) {
|
|
913
|
+
yield flushIntoChild();
|
|
1078
914
|
}
|
|
1079
915
|
}
|
|
916
|
+
const tailXPath = buildXPathFromSteps(buf);
|
|
917
|
+
return { targetFrameId: ctxFrameId, tailXPath, absPrefix };
|
|
1080
918
|
});
|
|
1081
919
|
}
|
|
1082
|
-
function
|
|
920
|
+
function resolveCssFocusFrameAndTail(page, rawSelector, parentByFrame, rootId) {
|
|
1083
921
|
return __async(this, null, function* () {
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
try {
|
|
1087
|
-
const { root } = yield session.send(
|
|
1088
|
-
"DOM.getDocument",
|
|
1089
|
-
{ depth, pierce }
|
|
1090
|
-
);
|
|
1091
|
-
if (depth !== -1) {
|
|
1092
|
-
yield hydrateDomTree(session, root, pierce);
|
|
1093
|
-
}
|
|
1094
|
-
return root;
|
|
1095
|
-
} catch (err) {
|
|
1096
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1097
|
-
if (isCborStackError(message)) {
|
|
1098
|
-
lastCborMessage = message;
|
|
1099
|
-
continue;
|
|
1100
|
-
}
|
|
1101
|
-
throw err;
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
throw new StagehandDomProcessError(
|
|
1105
|
-
lastCborMessage ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}` : "CDP DOM.getDocument failed after adaptive depth retries."
|
|
1106
|
-
);
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
function captureHybridSnapshot(page, options) {
|
|
1110
|
-
return __async(this, null, function* () {
|
|
1111
|
-
var _a4, _b, _c, _d2, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
1112
|
-
const pierce = (_a4 = options == null ? void 0 : options.pierceShadow) != null ? _a4 : true;
|
|
1113
|
-
const rootId = page.mainFrameId();
|
|
1114
|
-
const frameTree = page.asProtocolFrameTree(rootId);
|
|
1115
|
-
const parentByFrame = /* @__PURE__ */ new Map();
|
|
1116
|
-
(function index(n, parent) {
|
|
1117
|
-
var _a5;
|
|
1118
|
-
parentByFrame.set(n.frame.id, parent);
|
|
1119
|
-
for (const c of (_a5 = n.childFrames) != null ? _a5 : []) index(c, n.frame.id);
|
|
1120
|
-
})(frameTree, null);
|
|
1121
|
-
const frames = page.listAllFrameIds();
|
|
1122
|
-
const combinedXpathMap = {};
|
|
1123
|
-
const combinedUrlMap = {};
|
|
1124
|
-
const perFrameOutlines = [];
|
|
1125
|
-
const perFrameMaps = /* @__PURE__ */ new Map();
|
|
1126
|
-
const requestedFocus = (_b = options == null ? void 0 : options.focusSelector) == null ? void 0 : _b.trim();
|
|
1127
|
-
if (requestedFocus) {
|
|
1128
|
-
const logScopeFallback = () => {
|
|
1129
|
-
var _a5;
|
|
1130
|
-
v3Logger({
|
|
1131
|
-
message: `Unable to narrow scope with selector. Falling back to using full DOM`,
|
|
1132
|
-
level: 1,
|
|
1133
|
-
auxiliary: {
|
|
1134
|
-
arguments: {
|
|
1135
|
-
value: `selector: ${(_a5 = options == null ? void 0 : options.focusSelector) == null ? void 0 : _a5.trim()}`,
|
|
1136
|
-
type: "string"
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
});
|
|
1140
|
-
};
|
|
1141
|
-
try {
|
|
1142
|
-
let targetFrameId;
|
|
1143
|
-
let tailSelector;
|
|
1144
|
-
let absPrefix2;
|
|
1145
|
-
const looksLikeXPath = /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith("/");
|
|
1146
|
-
if (looksLikeXPath) {
|
|
1147
|
-
const focus = normalizeXPath(requestedFocus);
|
|
1148
|
-
const hit = yield resolveFocusFrameAndTail(
|
|
1149
|
-
page,
|
|
1150
|
-
focus,
|
|
1151
|
-
parentByFrame,
|
|
1152
|
-
rootId
|
|
1153
|
-
);
|
|
1154
|
-
targetFrameId = hit.targetFrameId;
|
|
1155
|
-
tailSelector = hit.tailXPath || void 0;
|
|
1156
|
-
absPrefix2 = hit.absPrefix;
|
|
1157
|
-
} else {
|
|
1158
|
-
const cssHit = yield resolveCssFocusFrameAndTail(
|
|
1159
|
-
page,
|
|
1160
|
-
requestedFocus,
|
|
1161
|
-
parentByFrame,
|
|
1162
|
-
rootId
|
|
1163
|
-
);
|
|
1164
|
-
targetFrameId = cssHit.targetFrameId;
|
|
1165
|
-
tailSelector = cssHit.tailSelector || void 0;
|
|
1166
|
-
absPrefix2 = cssHit.absPrefix;
|
|
1167
|
-
}
|
|
1168
|
-
const owningSess = ownerSession(page, targetFrameId);
|
|
1169
|
-
const parentId = parentByFrame.get(targetFrameId);
|
|
1170
|
-
const sameSessionAsParent = !!parentId && ownerSession(page, parentId) === ownerSession(page, targetFrameId);
|
|
1171
|
-
const { tagNameMap, xpathMap, scrollableMap } = yield domMapsForSession(
|
|
1172
|
-
owningSess,
|
|
1173
|
-
targetFrameId,
|
|
1174
|
-
pierce,
|
|
1175
|
-
(fid, be) => `${page.getOrdinal(fid)}-${be}`,
|
|
1176
|
-
/*attemptOwnerLookup=*/
|
|
1177
|
-
sameSessionAsParent
|
|
1178
|
-
);
|
|
1179
|
-
const { outline, urlMap, scopeApplied } = yield a11yForFrame(
|
|
1180
|
-
owningSess,
|
|
1181
|
-
targetFrameId,
|
|
1182
|
-
{
|
|
1183
|
-
focusSelector: tailSelector || void 0,
|
|
1184
|
-
tagNameMap,
|
|
1185
|
-
experimental: (_c = options == null ? void 0 : options.experimental) != null ? _c : false,
|
|
1186
|
-
scrollableMap,
|
|
1187
|
-
encode: (backendNodeId) => `${page.getOrdinal(targetFrameId)}-${backendNodeId}`
|
|
1188
|
-
}
|
|
1189
|
-
);
|
|
1190
|
-
const combinedXpathMap2 = {};
|
|
1191
|
-
const abs = absPrefix2 != null ? absPrefix2 : "";
|
|
1192
|
-
const isRoot = !abs || abs === "/";
|
|
1193
|
-
if (isRoot) {
|
|
1194
|
-
Object.assign(combinedXpathMap2, xpathMap);
|
|
1195
|
-
} else {
|
|
1196
|
-
for (const [encId, xp] of Object.entries(xpathMap)) {
|
|
1197
|
-
combinedXpathMap2[encId] = prefixXPath(abs, xp);
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
const combinedUrlMap2 = __spreadValues({}, urlMap);
|
|
1201
|
-
const snapshot = {
|
|
1202
|
-
combinedTree: outline,
|
|
1203
|
-
combinedXpathMap: combinedXpathMap2,
|
|
1204
|
-
combinedUrlMap: combinedUrlMap2,
|
|
1205
|
-
perFrame: [
|
|
1206
|
-
{
|
|
1207
|
-
frameId: targetFrameId,
|
|
1208
|
-
outline,
|
|
1209
|
-
xpathMap,
|
|
1210
|
-
urlMap
|
|
1211
|
-
}
|
|
1212
|
-
]
|
|
1213
|
-
};
|
|
1214
|
-
if (scopeApplied) {
|
|
1215
|
-
return snapshot;
|
|
1216
|
-
}
|
|
1217
|
-
logScopeFallback();
|
|
1218
|
-
} catch (e2) {
|
|
1219
|
-
logScopeFallback();
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
function buildSessionDomIndex(session, pierce2) {
|
|
1223
|
-
return __async(this, null, function* () {
|
|
1224
|
-
var _a5, _b2;
|
|
1225
|
-
yield session.send("DOM.enable").catch(() => {
|
|
1226
|
-
});
|
|
1227
|
-
const root = yield getDomTreeWithFallback(session, pierce2);
|
|
1228
|
-
const absByBe = /* @__PURE__ */ new Map();
|
|
1229
|
-
const tagByBe = /* @__PURE__ */ new Map();
|
|
1230
|
-
const scrollByBe = /* @__PURE__ */ new Map();
|
|
1231
|
-
const docRootOf = /* @__PURE__ */ new Map();
|
|
1232
|
-
const contentDocRootByIframe = /* @__PURE__ */ new Map();
|
|
1233
|
-
const rootBe = root.backendNodeId;
|
|
1234
|
-
const stack = [{ node: root, xp: "/", docRootBe: rootBe }];
|
|
1235
|
-
while (stack.length) {
|
|
1236
|
-
const { node, xp, docRootBe } = stack.pop();
|
|
1237
|
-
if (node.backendNodeId) {
|
|
1238
|
-
absByBe.set(node.backendNodeId, xp || "/");
|
|
1239
|
-
tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());
|
|
1240
|
-
if ((node == null ? void 0 : node.isScrollable) === true)
|
|
1241
|
-
scrollByBe.set(node.backendNodeId, true);
|
|
1242
|
-
docRootOf.set(node.backendNodeId, docRootBe);
|
|
1243
|
-
}
|
|
1244
|
-
const kids = (_a5 = node.children) != null ? _a5 : [];
|
|
1245
|
-
if (kids.length) {
|
|
1246
|
-
const segs = buildChildXPathSegments(kids);
|
|
1247
|
-
for (let i2 = kids.length - 1; i2 >= 0; i2--) {
|
|
1248
|
-
const child = kids[i2];
|
|
1249
|
-
const step = segs[i2];
|
|
1250
|
-
stack.push({ node: child, xp: joinXPath(xp, step), docRootBe });
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
for (const sr of (_b2 = node.shadowRoots) != null ? _b2 : []) {
|
|
1254
|
-
stack.push({ node: sr, xp: joinXPath(xp, "//"), docRootBe });
|
|
1255
|
-
}
|
|
1256
|
-
const cd = node.contentDocument;
|
|
1257
|
-
if (cd && typeof cd.backendNodeId === "number") {
|
|
1258
|
-
contentDocRootByIframe.set(node.backendNodeId, cd.backendNodeId);
|
|
1259
|
-
stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
return {
|
|
1263
|
-
rootBackend: rootBe,
|
|
1264
|
-
absByBe,
|
|
1265
|
-
tagByBe,
|
|
1266
|
-
scrollByBe,
|
|
1267
|
-
docRootOf,
|
|
1268
|
-
contentDocRootByIframe
|
|
1269
|
-
};
|
|
1270
|
-
});
|
|
1271
|
-
}
|
|
1272
|
-
function relativizeXPath(baseAbs, nodeAbs) {
|
|
1273
|
-
const base = normalizeXPath(baseAbs);
|
|
1274
|
-
const abs = normalizeXPath(nodeAbs);
|
|
1275
|
-
if (abs === base) return "/";
|
|
1276
|
-
if (abs.startsWith(base)) {
|
|
1277
|
-
const tail = abs.slice(base.length);
|
|
1278
|
-
if (!tail) return "/";
|
|
1279
|
-
return tail.startsWith("/") || tail.startsWith("//") ? tail : `/${tail}`;
|
|
1280
|
-
}
|
|
1281
|
-
if (base === "/") return abs;
|
|
1282
|
-
return abs;
|
|
1283
|
-
}
|
|
1284
|
-
const sessionToIndex = /* @__PURE__ */ new Map();
|
|
1285
|
-
const sessionById = /* @__PURE__ */ new Map();
|
|
1286
|
-
for (const frameId of frames) {
|
|
1287
|
-
const sess = ownerSession(page, frameId);
|
|
1288
|
-
const sid = (_d2 = sess.id) != null ? _d2 : "root";
|
|
1289
|
-
if (!sessionById.has(sid)) sessionById.set(sid, sess);
|
|
1290
|
-
}
|
|
1291
|
-
for (const [sid, sess] of sessionById.entries()) {
|
|
1292
|
-
const idx = yield buildSessionDomIndex(sess, pierce);
|
|
1293
|
-
sessionToIndex.set(sid, idx);
|
|
1294
|
-
}
|
|
1295
|
-
for (const frameId of frames) {
|
|
1296
|
-
const sess = ownerSession(page, frameId);
|
|
1297
|
-
const sid = (_e = sess.id) != null ? _e : "root";
|
|
1298
|
-
let idx = sessionToIndex.get(sid);
|
|
1299
|
-
if (!idx) {
|
|
1300
|
-
idx = yield buildSessionDomIndex(sess, pierce);
|
|
1301
|
-
sessionToIndex.set(sid, idx);
|
|
1302
|
-
}
|
|
1303
|
-
const parentId = parentByFrame.get(frameId);
|
|
1304
|
-
const sameSessionAsParent = !!parentId && ownerSession(page, parentId) === sess;
|
|
1305
|
-
let docRootBe = idx.rootBackend;
|
|
1306
|
-
if (sameSessionAsParent) {
|
|
1307
|
-
try {
|
|
1308
|
-
const { backendNodeId } = yield sess.send(
|
|
1309
|
-
"DOM.getFrameOwner",
|
|
1310
|
-
{ frameId }
|
|
1311
|
-
);
|
|
1312
|
-
if (typeof backendNodeId === "number") {
|
|
1313
|
-
const cdBe = idx.contentDocRootByIframe.get(backendNodeId);
|
|
1314
|
-
if (typeof cdBe === "number") docRootBe = cdBe;
|
|
1315
|
-
}
|
|
1316
|
-
} catch (e2) {
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
const tagNameMap = {};
|
|
1320
|
-
const xpathMap = {};
|
|
1321
|
-
const scrollableMap = {};
|
|
1322
|
-
const enc = (be) => `${page.getOrdinal(frameId)}-${be}`;
|
|
1323
|
-
const baseAbs = (_f = idx.absByBe.get(docRootBe)) != null ? _f : "/";
|
|
1324
|
-
for (const [be, nodeAbs] of idx.absByBe.entries()) {
|
|
1325
|
-
const nodeDocRoot = idx.docRootOf.get(be);
|
|
1326
|
-
if (nodeDocRoot !== docRootBe) continue;
|
|
1327
|
-
const rel = relativizeXPath(baseAbs, nodeAbs);
|
|
1328
|
-
const key = enc(be);
|
|
1329
|
-
xpathMap[key] = rel;
|
|
1330
|
-
const tag = idx.tagByBe.get(be);
|
|
1331
|
-
if (tag) tagNameMap[key] = tag;
|
|
1332
|
-
if (idx.scrollByBe.get(be)) scrollableMap[key] = true;
|
|
1333
|
-
}
|
|
1334
|
-
const { outline, urlMap } = yield a11yForFrame(sess, frameId, {
|
|
1335
|
-
experimental: (_g = options == null ? void 0 : options.experimental) != null ? _g : false,
|
|
1336
|
-
tagNameMap,
|
|
1337
|
-
scrollableMap,
|
|
1338
|
-
encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`
|
|
1339
|
-
});
|
|
1340
|
-
perFrameOutlines.push({ frameId, outline });
|
|
1341
|
-
perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });
|
|
1342
|
-
}
|
|
1343
|
-
const absPrefix = /* @__PURE__ */ new Map();
|
|
1344
|
-
const iframeHostEncByChild = /* @__PURE__ */ new Map();
|
|
1345
|
-
absPrefix.set(rootId, "");
|
|
1346
|
-
const queue = [rootId];
|
|
1347
|
-
while (queue.length) {
|
|
1348
|
-
const parent = queue.shift();
|
|
1349
|
-
const parentAbs = absPrefix.get(parent);
|
|
1350
|
-
for (const child of frames) {
|
|
1351
|
-
if (parentByFrame.get(child) !== parent) continue;
|
|
1352
|
-
queue.push(child);
|
|
1353
|
-
const parentSess = parentSession(page, parentByFrame, child);
|
|
1354
|
-
const ownerBackendNodeId = yield (() => __async(null, null, function* () {
|
|
1355
|
-
try {
|
|
1356
|
-
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: child });
|
|
1357
|
-
return backendNodeId;
|
|
1358
|
-
} catch (e2) {
|
|
1359
|
-
return void 0;
|
|
1360
|
-
}
|
|
1361
|
-
}))();
|
|
1362
|
-
if (!ownerBackendNodeId) {
|
|
1363
|
-
absPrefix.set(child, parentAbs);
|
|
1364
|
-
continue;
|
|
1365
|
-
}
|
|
1366
|
-
const parentDom = perFrameMaps.get(parent);
|
|
1367
|
-
const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;
|
|
1368
|
-
const iframeXPath = parentDom == null ? void 0 : parentDom.xpathMap[iframeEnc];
|
|
1369
|
-
const childAbs = iframeXPath ? prefixXPath(parentAbs || "/", iframeXPath) : parentAbs;
|
|
1370
|
-
absPrefix.set(child, childAbs);
|
|
1371
|
-
iframeHostEncByChild.set(child, iframeEnc);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
for (const frameId of frames) {
|
|
1375
|
-
const maps = perFrameMaps.get(frameId);
|
|
1376
|
-
if (!maps) continue;
|
|
1377
|
-
const abs = (_h = absPrefix.get(frameId)) != null ? _h : "";
|
|
1378
|
-
const isRoot = abs === "" || abs === "/";
|
|
1379
|
-
if (isRoot) {
|
|
1380
|
-
Object.assign(combinedXpathMap, maps.xpathMap);
|
|
1381
|
-
Object.assign(combinedUrlMap, maps.urlMap);
|
|
1382
|
-
continue;
|
|
1383
|
-
}
|
|
1384
|
-
for (const [encId, xp] of Object.entries(maps.xpathMap)) {
|
|
1385
|
-
combinedXpathMap[encId] = prefixXPath(abs, xp);
|
|
1386
|
-
}
|
|
1387
|
-
Object.assign(combinedUrlMap, maps.urlMap);
|
|
1388
|
-
}
|
|
1389
|
-
const idToTree = /* @__PURE__ */ new Map();
|
|
1390
|
-
for (const { frameId, outline } of perFrameOutlines) {
|
|
1391
|
-
const parentEnc = iframeHostEncByChild.get(frameId);
|
|
1392
|
-
if (parentEnc) idToTree.set(parentEnc, outline);
|
|
1393
|
-
}
|
|
1394
|
-
const rootOutline = (_l = (_k = (_i = perFrameOutlines.find((o) => o.frameId === rootId)) == null ? void 0 : _i.outline) != null ? _k : (_j = perFrameOutlines[0]) == null ? void 0 : _j.outline) != null ? _l : "";
|
|
1395
|
-
const combinedTree = injectSubtrees(rootOutline, idToTree);
|
|
1396
|
-
return {
|
|
1397
|
-
combinedTree,
|
|
1398
|
-
combinedXpathMap,
|
|
1399
|
-
combinedUrlMap,
|
|
1400
|
-
perFrame: perFrameOutlines.map(({ frameId, outline }) => {
|
|
1401
|
-
var _a5, _b2;
|
|
1402
|
-
const maps = perFrameMaps.get(frameId);
|
|
1403
|
-
return {
|
|
1404
|
-
frameId,
|
|
1405
|
-
outline,
|
|
1406
|
-
xpathMap: (_a5 = maps == null ? void 0 : maps.xpathMap) != null ? _a5 : {},
|
|
1407
|
-
urlMap: (_b2 = maps == null ? void 0 : maps.urlMap) != null ? _b2 : {}
|
|
1408
|
-
};
|
|
1409
|
-
})
|
|
1410
|
-
};
|
|
1411
|
-
});
|
|
1412
|
-
}
|
|
1413
|
-
function prefixXPath(parentAbs, child) {
|
|
1414
|
-
const p = parentAbs === "/" ? "" : parentAbs.replace(/\/$/, "");
|
|
1415
|
-
if (!child || child === "/") return p || "/";
|
|
1416
|
-
if (child.startsWith("//"))
|
|
1417
|
-
return p ? `${p}//${child.slice(2)}` : `//${child.slice(2)}`;
|
|
1418
|
-
const c = child.replace(/^\//, "");
|
|
1419
|
-
return p ? `${p}/${c}` : `/${c}`;
|
|
1420
|
-
}
|
|
1421
|
-
function normalizeXPath(x2) {
|
|
1422
|
-
if (!x2) return "";
|
|
1423
|
-
let s2 = x2.trim().replace(/^xpath=/i, "");
|
|
1424
|
-
if (!s2.startsWith("/")) s2 = "/" + s2;
|
|
1425
|
-
if (s2.length > 1 && s2.endsWith("/")) s2 = s2.slice(0, -1);
|
|
1426
|
-
return s2;
|
|
1427
|
-
}
|
|
1428
|
-
function parseXPathToSteps(path8) {
|
|
1429
|
-
const s2 = path8.trim();
|
|
1430
|
-
let i2 = 0;
|
|
1431
|
-
const steps = [];
|
|
1432
|
-
while (i2 < s2.length) {
|
|
1433
|
-
let axis = "child";
|
|
1434
|
-
if (s2.startsWith("//", i2)) {
|
|
1435
|
-
axis = "desc";
|
|
1436
|
-
i2 += 2;
|
|
1437
|
-
} else if (s2[i2] === "/") {
|
|
1438
|
-
axis = "child";
|
|
1439
|
-
i2 += 1;
|
|
1440
|
-
}
|
|
1441
|
-
const start = i2;
|
|
1442
|
-
while (i2 < s2.length && s2[i2] !== "/") i2++;
|
|
1443
|
-
const raw = s2.slice(start, i2).trim();
|
|
1444
|
-
if (!raw) continue;
|
|
1445
|
-
const name = raw.replace(/\[\d+\]\s*$/u, "").toLowerCase();
|
|
1446
|
-
steps.push({ axis, raw, name });
|
|
1447
|
-
}
|
|
1448
|
-
return steps;
|
|
1449
|
-
}
|
|
1450
|
-
function buildXPathFromSteps(steps) {
|
|
1451
|
-
let out = "";
|
|
1452
|
-
for (const st of steps) {
|
|
1453
|
-
out += st.axis === "desc" ? "//" : "/";
|
|
1454
|
-
out += st.raw;
|
|
1455
|
-
}
|
|
1456
|
-
return out || "/";
|
|
1457
|
-
}
|
|
1458
|
-
function resolveFocusFrameAndTail(page, absoluteXPath, parentByFrame, rootId) {
|
|
1459
|
-
return __async(this, null, function* () {
|
|
1460
|
-
const steps = parseXPathToSteps(absoluteXPath);
|
|
922
|
+
var _a4;
|
|
923
|
+
const parts = rawSelector.split(">>").map((s2) => s2.trim()).filter(Boolean);
|
|
1461
924
|
let ctxFrameId = rootId;
|
|
1462
|
-
|
|
1463
|
-
let
|
|
1464
|
-
const flushIntoChild = () => __async(null, null, function* () {
|
|
1465
|
-
if (!buf.length) return;
|
|
1466
|
-
const selectorForIframe = buildXPathFromSteps(buf);
|
|
925
|
+
const absPrefix = "";
|
|
926
|
+
for (let i2 = 0; i2 < Math.max(0, parts.length - 1); i2++) {
|
|
1467
927
|
const parentSess = page.getSessionForFrame(ctxFrameId);
|
|
1468
|
-
const objectId = yield
|
|
928
|
+
const objectId = yield resolveObjectIdForCss(
|
|
1469
929
|
parentSess,
|
|
1470
|
-
|
|
930
|
+
parts[i2],
|
|
1471
931
|
ctxFrameId
|
|
1472
932
|
);
|
|
1473
933
|
if (!objectId)
|
|
1474
934
|
throw new StagehandIframeError(
|
|
1475
|
-
|
|
1476
|
-
"Failed to resolve iframe
|
|
935
|
+
parts[i2],
|
|
936
|
+
"Failed to resolve iframe via CSS hop"
|
|
1477
937
|
);
|
|
1478
938
|
try {
|
|
1479
939
|
yield parentSess.send("DOM.enable").catch(() => {
|
|
@@ -1492,246 +952,22 @@ function resolveFocusFrameAndTail(page, absoluteXPath, parentByFrame, rootId) {
|
|
|
1492
952
|
break;
|
|
1493
953
|
}
|
|
1494
954
|
} catch (e2) {
|
|
955
|
+
continue;
|
|
1495
956
|
}
|
|
1496
957
|
}
|
|
1497
958
|
if (!childFrameId)
|
|
1498
959
|
throw new StagehandIframeError(
|
|
1499
|
-
|
|
1500
|
-
"Could not map iframe to child frameId"
|
|
960
|
+
parts[i2],
|
|
961
|
+
"Could not map CSS iframe hop to child frameId"
|
|
1501
962
|
);
|
|
1502
|
-
absPrefix = prefixXPath(absPrefix || "/", selectorForIframe);
|
|
1503
963
|
ctxFrameId = childFrameId;
|
|
1504
964
|
} finally {
|
|
1505
965
|
yield parentSess.send("Runtime.releaseObject", { objectId }).catch(() => {
|
|
1506
966
|
});
|
|
1507
967
|
}
|
|
1508
|
-
buf = [];
|
|
1509
|
-
});
|
|
1510
|
-
for (const st of steps) {
|
|
1511
|
-
buf.push(st);
|
|
1512
|
-
if (IFRAME_STEP_RE.test(st.name)) {
|
|
1513
|
-
yield flushIntoChild();
|
|
1514
|
-
}
|
|
1515
968
|
}
|
|
1516
|
-
const
|
|
1517
|
-
return { targetFrameId: ctxFrameId,
|
|
1518
|
-
});
|
|
1519
|
-
}
|
|
1520
|
-
function resolveCssFocusFrameAndTail(page, rawSelector, parentByFrame, rootId) {
|
|
1521
|
-
return __async(this, null, function* () {
|
|
1522
|
-
var _a4;
|
|
1523
|
-
const parts = rawSelector.split(">>").map((s2) => s2.trim()).filter(Boolean);
|
|
1524
|
-
let ctxFrameId = rootId;
|
|
1525
|
-
const absPrefix = "";
|
|
1526
|
-
for (let i2 = 0; i2 < Math.max(0, parts.length - 1); i2++) {
|
|
1527
|
-
const parentSess = page.getSessionForFrame(ctxFrameId);
|
|
1528
|
-
const objectId = yield resolveObjectIdForCss(
|
|
1529
|
-
parentSess,
|
|
1530
|
-
parts[i2],
|
|
1531
|
-
ctxFrameId
|
|
1532
|
-
);
|
|
1533
|
-
if (!objectId)
|
|
1534
|
-
throw new StagehandIframeError(
|
|
1535
|
-
parts[i2],
|
|
1536
|
-
"Failed to resolve iframe via CSS hop"
|
|
1537
|
-
);
|
|
1538
|
-
try {
|
|
1539
|
-
yield parentSess.send("DOM.enable").catch(() => {
|
|
1540
|
-
});
|
|
1541
|
-
const desc = yield parentSess.send(
|
|
1542
|
-
"DOM.describeNode",
|
|
1543
|
-
{ objectId }
|
|
1544
|
-
);
|
|
1545
|
-
const iframeBackendNodeId = desc.node.backendNodeId;
|
|
1546
|
-
let childFrameId;
|
|
1547
|
-
for (const fid of listChildrenOf(parentByFrame, ctxFrameId)) {
|
|
1548
|
-
try {
|
|
1549
|
-
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: fid });
|
|
1550
|
-
if (backendNodeId === iframeBackendNodeId) {
|
|
1551
|
-
childFrameId = fid;
|
|
1552
|
-
break;
|
|
1553
|
-
}
|
|
1554
|
-
} catch (e2) {
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
if (!childFrameId)
|
|
1558
|
-
throw new StagehandIframeError(
|
|
1559
|
-
parts[i2],
|
|
1560
|
-
"Could not map CSS iframe hop to child frameId"
|
|
1561
|
-
);
|
|
1562
|
-
ctxFrameId = childFrameId;
|
|
1563
|
-
} finally {
|
|
1564
|
-
yield parentSess.send("Runtime.releaseObject", { objectId }).catch(() => {
|
|
1565
|
-
});
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
const tailSelector = (_a4 = parts[parts.length - 1]) != null ? _a4 : "*";
|
|
1569
|
-
return { targetFrameId: ctxFrameId, tailSelector, absPrefix };
|
|
1570
|
-
});
|
|
1571
|
-
}
|
|
1572
|
-
function listChildrenOf(parentByFrame, parentId) {
|
|
1573
|
-
const out = [];
|
|
1574
|
-
for (const [fid, p] of parentByFrame.entries()) {
|
|
1575
|
-
if (p === parentId) out.push(fid);
|
|
1576
|
-
}
|
|
1577
|
-
return out;
|
|
1578
|
-
}
|
|
1579
|
-
function domMapsForSession(session, frameId, pierce, encode = (fid, be) => `${fid}-${be}`, attemptOwnerLookup = true) {
|
|
1580
|
-
return __async(this, null, function* () {
|
|
1581
|
-
var _a4, _b;
|
|
1582
|
-
yield session.send("DOM.enable").catch(() => {
|
|
1583
|
-
});
|
|
1584
|
-
const root = yield getDomTreeWithFallback(session, pierce);
|
|
1585
|
-
let startNode = root;
|
|
1586
|
-
if (attemptOwnerLookup) {
|
|
1587
|
-
try {
|
|
1588
|
-
const owner = yield session.send(
|
|
1589
|
-
"DOM.getFrameOwner",
|
|
1590
|
-
{ frameId }
|
|
1591
|
-
);
|
|
1592
|
-
const ownerBackendId = owner.backendNodeId;
|
|
1593
|
-
if (typeof ownerBackendId === "number") {
|
|
1594
|
-
const ownerEl = findNodeByBackendId(root, ownerBackendId);
|
|
1595
|
-
if (ownerEl == null ? void 0 : ownerEl.contentDocument) {
|
|
1596
|
-
startNode = ownerEl.contentDocument;
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
} catch (e2) {
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
const tagNameMap = {};
|
|
1603
|
-
const xpathMap = {};
|
|
1604
|
-
const scrollableMap = {};
|
|
1605
|
-
const stack = [{ node: startNode, xpath: "" }];
|
|
1606
|
-
while (stack.length) {
|
|
1607
|
-
const { node, xpath } = stack.pop();
|
|
1608
|
-
if (node.backendNodeId) {
|
|
1609
|
-
const encId = encode(frameId, node.backendNodeId);
|
|
1610
|
-
tagNameMap[encId] = String(node.nodeName).toLowerCase();
|
|
1611
|
-
xpathMap[encId] = xpath || "/";
|
|
1612
|
-
const isScrollable = (node == null ? void 0 : node.isScrollable) === true;
|
|
1613
|
-
if (isScrollable) scrollableMap[encId] = true;
|
|
1614
|
-
}
|
|
1615
|
-
const kids = (_a4 = node.children) != null ? _a4 : [];
|
|
1616
|
-
if (kids.length) {
|
|
1617
|
-
const segs = buildChildXPathSegments(kids);
|
|
1618
|
-
for (let i2 = kids.length - 1; i2 >= 0; i2--) {
|
|
1619
|
-
const child = kids[i2];
|
|
1620
|
-
const step = segs[i2];
|
|
1621
|
-
stack.push({
|
|
1622
|
-
node: child,
|
|
1623
|
-
xpath: joinXPath(xpath, step)
|
|
1624
|
-
});
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
for (const sr of (_b = node.shadowRoots) != null ? _b : []) {
|
|
1628
|
-
stack.push({
|
|
1629
|
-
node: sr,
|
|
1630
|
-
xpath: joinXPath(xpath, "//")
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
return { tagNameMap, xpathMap, scrollableMap };
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
function buildChildXPathSegments(kids) {
|
|
1638
|
-
var _a4;
|
|
1639
|
-
const segs = [];
|
|
1640
|
-
const ctr = {};
|
|
1641
|
-
for (const child of kids) {
|
|
1642
|
-
const tag = String(child.nodeName).toLowerCase();
|
|
1643
|
-
const key = `${child.nodeType}:${tag}`;
|
|
1644
|
-
const idx = ctr[key] = ((_a4 = ctr[key]) != null ? _a4 : 0) + 1;
|
|
1645
|
-
if (child.nodeType === 3) {
|
|
1646
|
-
segs.push(`text()[${idx}]`);
|
|
1647
|
-
} else if (child.nodeType === 8) {
|
|
1648
|
-
segs.push(`comment()[${idx}]`);
|
|
1649
|
-
} else {
|
|
1650
|
-
segs.push(
|
|
1651
|
-
tag.includes(":") ? `*[name()='${tag}'][${idx}]` : `${tag}[${idx}]`
|
|
1652
|
-
);
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
return segs;
|
|
1656
|
-
}
|
|
1657
|
-
function joinXPath(base, step) {
|
|
1658
|
-
if (step === "//") {
|
|
1659
|
-
if (!base || base === "/") return "//";
|
|
1660
|
-
return base.endsWith("/") ? `${base}/` : `${base}//`;
|
|
1661
|
-
}
|
|
1662
|
-
if (!base || base === "/") return step ? `/${step}` : "/";
|
|
1663
|
-
if (base.endsWith("//")) return `${base}${step}`;
|
|
1664
|
-
if (!step) return base;
|
|
1665
|
-
return `${base}/${step}`;
|
|
1666
|
-
}
|
|
1667
|
-
function a11yForFrame(session, frameId, opts) {
|
|
1668
|
-
return __async(this, null, function* () {
|
|
1669
|
-
var _a4, _b;
|
|
1670
|
-
yield session.send("Accessibility.enable").catch(() => {
|
|
1671
|
-
});
|
|
1672
|
-
yield session.send("Runtime.enable").catch(() => {
|
|
1673
|
-
});
|
|
1674
|
-
yield session.send("DOM.enable").catch(() => {
|
|
1675
|
-
});
|
|
1676
|
-
let nodes = [];
|
|
1677
|
-
try {
|
|
1678
|
-
const params = frameId ? { frameId } : {};
|
|
1679
|
-
({ nodes } = yield session.send("Accessibility.getFullAXTree", params));
|
|
1680
|
-
} catch (e2) {
|
|
1681
|
-
const msg = String((_b = (_a4 = e2 == null ? void 0 : e2.message) != null ? _a4 : e2) != null ? _b : "");
|
|
1682
|
-
const isFrameScopeError = msg.includes("Frame with the given") || msg.includes("does not belong to the target") || msg.includes("is not found");
|
|
1683
|
-
if (!isFrameScopeError || !frameId) throw e2;
|
|
1684
|
-
({ nodes } = yield session.send("Accessibility.getFullAXTree"));
|
|
1685
|
-
}
|
|
1686
|
-
const urlMap = {};
|
|
1687
|
-
for (const n of nodes) {
|
|
1688
|
-
const be = n.backendDOMNodeId;
|
|
1689
|
-
if (typeof be !== "number") continue;
|
|
1690
|
-
const url = extractUrlFromAXNode(n);
|
|
1691
|
-
if (!url) continue;
|
|
1692
|
-
const enc = opts.encode(be);
|
|
1693
|
-
urlMap[enc] = url;
|
|
1694
|
-
}
|
|
1695
|
-
let scopeApplied = false;
|
|
1696
|
-
const nodesForOutline = yield (() => __async(null, null, function* () {
|
|
1697
|
-
var _a5, _b2, _c;
|
|
1698
|
-
const sel = (_a5 = opts.focusSelector) == null ? void 0 : _a5.trim();
|
|
1699
|
-
if (!sel) return nodes;
|
|
1700
|
-
try {
|
|
1701
|
-
const looksLikeXPath = /^xpath=/i.test(sel) || sel.startsWith("/");
|
|
1702
|
-
const objectId = looksLikeXPath ? yield resolveObjectIdForXPath(session, sel, frameId) : yield resolveObjectIdForCss(session, sel, frameId);
|
|
1703
|
-
if (!objectId) return nodes;
|
|
1704
|
-
const desc = yield session.send(
|
|
1705
|
-
"DOM.describeNode",
|
|
1706
|
-
{ objectId }
|
|
1707
|
-
);
|
|
1708
|
-
const be = (_b2 = desc.node) == null ? void 0 : _b2.backendNodeId;
|
|
1709
|
-
if (typeof be !== "number") return nodes;
|
|
1710
|
-
const target = nodes.find((n) => n.backendDOMNodeId === be);
|
|
1711
|
-
if (!target) return nodes;
|
|
1712
|
-
scopeApplied = true;
|
|
1713
|
-
const keep = /* @__PURE__ */ new Set([target.nodeId]);
|
|
1714
|
-
const queue = [target];
|
|
1715
|
-
while (queue.length) {
|
|
1716
|
-
const cur = queue.shift();
|
|
1717
|
-
for (const id of (_c = cur.childIds) != null ? _c : []) {
|
|
1718
|
-
if (keep.has(id)) continue;
|
|
1719
|
-
keep.add(id);
|
|
1720
|
-
const child = nodes.find((n) => n.nodeId === id);
|
|
1721
|
-
if (child) queue.push(child);
|
|
1722
|
-
}
|
|
1723
|
-
}
|
|
1724
|
-
return nodes.filter((n) => keep.has(n.nodeId)).map(
|
|
1725
|
-
(n) => n.nodeId === target.nodeId ? __spreadProps(__spreadValues({}, n), { parentId: void 0 }) : n
|
|
1726
|
-
);
|
|
1727
|
-
} catch (e2) {
|
|
1728
|
-
return nodes;
|
|
1729
|
-
}
|
|
1730
|
-
}))();
|
|
1731
|
-
const decorated = decorateRoles(nodesForOutline, opts);
|
|
1732
|
-
const { tree } = yield buildHierarchicalTree(decorated, opts);
|
|
1733
|
-
const simplified = tree.map((n) => formatTreeLine(n)).join("\n");
|
|
1734
|
-
return { outline: simplified.trimEnd(), urlMap, scopeApplied };
|
|
969
|
+
const tailSelector = (_a4 = parts[parts.length - 1]) != null ? _a4 : "*";
|
|
970
|
+
return { targetFrameId: ctxFrameId, tailSelector, absPrefix };
|
|
1735
971
|
});
|
|
1736
972
|
}
|
|
1737
973
|
function resolveObjectIdForXPath(session, xpath, frameId) {
|
|
@@ -1803,89 +1039,25 @@ function resolveObjectIdForCss(session, selector, frameId) {
|
|
|
1803
1039
|
return evaluate(fallbackExpr);
|
|
1804
1040
|
});
|
|
1805
1041
|
}
|
|
1806
|
-
function
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
}
|
|
1811
|
-
return
|
|
1812
|
-
var _a4, _b, _c;
|
|
1813
|
-
let encodedId;
|
|
1814
|
-
if (typeof n.backendDOMNodeId === "number") {
|
|
1815
|
-
try {
|
|
1816
|
-
encodedId = opts.encode(n.backendDOMNodeId);
|
|
1817
|
-
} catch (e2) {
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
let role = asRole(n);
|
|
1821
|
-
const domIsScrollable = encodedId ? opts.scrollableMap[encodedId] === true : false;
|
|
1822
|
-
const tag = encodedId ? opts.tagNameMap[encodedId] : void 0;
|
|
1823
|
-
const isHtmlElement = tag === "html";
|
|
1824
|
-
if ((domIsScrollable || isHtmlElement) && tag !== "#document") {
|
|
1825
|
-
const tagLabel = tag && tag.startsWith("#") ? tag.slice(1) : tag;
|
|
1826
|
-
role = tagLabel ? `scrollable, ${tagLabel}` : `scrollable${role ? `, ${role}` : ""}`;
|
|
1827
|
-
}
|
|
1828
|
-
return {
|
|
1829
|
-
role,
|
|
1830
|
-
name: (_a4 = n.name) == null ? void 0 : _a4.value,
|
|
1831
|
-
description: (_b = n.description) == null ? void 0 : _b.value,
|
|
1832
|
-
value: (_c = n.value) == null ? void 0 : _c.value,
|
|
1833
|
-
nodeId: n.nodeId,
|
|
1834
|
-
backendDOMNodeId: n.backendDOMNodeId,
|
|
1835
|
-
parentId: n.parentId,
|
|
1836
|
-
childIds: n.childIds,
|
|
1837
|
-
encodedId
|
|
1838
|
-
};
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
|
-
function buildHierarchicalTree(nodes, opts) {
|
|
1842
|
-
return __async(this, null, function* () {
|
|
1843
|
-
var _a4;
|
|
1844
|
-
const nodeMap = /* @__PURE__ */ new Map();
|
|
1845
|
-
for (const n of nodes) {
|
|
1846
|
-
const keep = !!(n.name && n.name.trim()) || !!(n.childIds && n.childIds.length) || !isStructural(n.role);
|
|
1847
|
-
if (!keep) continue;
|
|
1848
|
-
nodeMap.set(n.nodeId, __spreadValues({}, n));
|
|
1849
|
-
}
|
|
1850
|
-
for (const n of nodes) {
|
|
1851
|
-
if (!n.parentId) continue;
|
|
1852
|
-
const parent = nodeMap.get(n.parentId);
|
|
1853
|
-
const cur = nodeMap.get(n.nodeId);
|
|
1854
|
-
if (parent && cur) ((_a4 = parent.children) != null ? _a4 : parent.children = []).push(cur);
|
|
1855
|
-
}
|
|
1856
|
-
const roots = nodes.filter((n) => !n.parentId && nodeMap.has(n.nodeId)).map((n) => nodeMap.get(n.nodeId));
|
|
1857
|
-
const cleaned = (yield Promise.all(roots.map(pruneStructuralSafe))).filter(
|
|
1858
|
-
Boolean
|
|
1859
|
-
);
|
|
1860
|
-
return { tree: cleaned };
|
|
1861
|
-
function pruneStructuralSafe(node) {
|
|
1862
|
-
return __async(this, null, function* () {
|
|
1863
|
-
var _a5;
|
|
1864
|
-
if (+node.nodeId < 0) return null;
|
|
1865
|
-
const children = (_a5 = node.children) != null ? _a5 : [];
|
|
1866
|
-
if (!children.length) {
|
|
1867
|
-
return isStructural(node.role) ? null : node;
|
|
1868
|
-
}
|
|
1869
|
-
const cleanedKids = (yield Promise.all(children.map(pruneStructuralSafe))).filter(Boolean);
|
|
1870
|
-
const prunedStatic = removeRedundantStaticTextChildren(node, cleanedKids);
|
|
1871
|
-
if (isStructural(node.role)) {
|
|
1872
|
-
if (prunedStatic.length === 1) return prunedStatic[0];
|
|
1873
|
-
if (prunedStatic.length === 0) return null;
|
|
1874
|
-
}
|
|
1875
|
-
let newRole = node.role;
|
|
1876
|
-
if ((newRole === "generic" || newRole === "none") && node.encodedId) {
|
|
1877
|
-
const tagName = opts.tagNameMap[node.encodedId];
|
|
1878
|
-
if (tagName) newRole = tagName;
|
|
1879
|
-
}
|
|
1880
|
-
if (newRole === "combobox" && node.encodedId) {
|
|
1881
|
-
const tagName = opts.tagNameMap[node.encodedId];
|
|
1882
|
-
if (tagName === "select") newRole = "select";
|
|
1883
|
-
}
|
|
1884
|
-
return __spreadProps(__spreadValues({}, node), { role: newRole, children: prunedStatic });
|
|
1885
|
-
});
|
|
1886
|
-
}
|
|
1887
|
-
});
|
|
1042
|
+
function listChildrenOf(parentByFrame, parentId) {
|
|
1043
|
+
const out = [];
|
|
1044
|
+
for (const [fid, p] of parentByFrame.entries()) {
|
|
1045
|
+
if (p === parentId) out.push(fid);
|
|
1046
|
+
}
|
|
1047
|
+
return out;
|
|
1888
1048
|
}
|
|
1049
|
+
var IFRAME_STEP_RE;
|
|
1050
|
+
var init_focusSelectors = __esm({
|
|
1051
|
+
"lib/v3/understudy/a11y/snapshot/focusSelectors.ts"() {
|
|
1052
|
+
init_executionContextRegistry();
|
|
1053
|
+
init_locatorInvocation();
|
|
1054
|
+
init_sdkErrors();
|
|
1055
|
+
init_xpathUtils();
|
|
1056
|
+
IFRAME_STEP_RE = /^iframe(?:\[\d+])?$/i;
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
// lib/v3/understudy/a11y/snapshot/treeFormatUtils.ts
|
|
1889
1061
|
function formatTreeLine(node, level = 0) {
|
|
1890
1062
|
var _a4, _b, _c;
|
|
1891
1063
|
const indent = " ".repeat(level);
|
|
@@ -1895,80 +1067,6 @@ function formatTreeLine(node, level = 0) {
|
|
|
1895
1067
|
return kids ? `${indent}${label}
|
|
1896
1068
|
${kids}` : `${indent}${label}`;
|
|
1897
1069
|
}
|
|
1898
|
-
function isStructural(role) {
|
|
1899
|
-
const r2 = role == null ? void 0 : role.toLowerCase();
|
|
1900
|
-
return r2 === "generic" || r2 === "none" || r2 === "inlinetextbox";
|
|
1901
|
-
}
|
|
1902
|
-
function cleanText(input) {
|
|
1903
|
-
const PUA_START = 57344;
|
|
1904
|
-
const PUA_END = 63743;
|
|
1905
|
-
const NBSP = /* @__PURE__ */ new Set([160, 8239, 8199, 65279]);
|
|
1906
|
-
let out = "";
|
|
1907
|
-
let prevSpace = false;
|
|
1908
|
-
for (let i2 = 0; i2 < input.length; i2++) {
|
|
1909
|
-
const code = input.charCodeAt(i2);
|
|
1910
|
-
if (code >= PUA_START && code <= PUA_END) continue;
|
|
1911
|
-
if (NBSP.has(code)) {
|
|
1912
|
-
if (!prevSpace) {
|
|
1913
|
-
out += " ";
|
|
1914
|
-
prevSpace = true;
|
|
1915
|
-
}
|
|
1916
|
-
continue;
|
|
1917
|
-
}
|
|
1918
|
-
out += input[i2];
|
|
1919
|
-
prevSpace = input[i2] === " ";
|
|
1920
|
-
}
|
|
1921
|
-
return out.trim();
|
|
1922
|
-
}
|
|
1923
|
-
function extractUrlFromAXNode(ax) {
|
|
1924
|
-
var _a4, _b;
|
|
1925
|
-
const props = (_a4 = ax.properties) != null ? _a4 : [];
|
|
1926
|
-
const urlProp = props.find((p) => p.name === "url");
|
|
1927
|
-
const value = (_b = urlProp == null ? void 0 : urlProp.value) == null ? void 0 : _b.value;
|
|
1928
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1929
|
-
}
|
|
1930
|
-
function normaliseSpaces(s2) {
|
|
1931
|
-
let out = "";
|
|
1932
|
-
let inWs = false;
|
|
1933
|
-
for (let i2 = 0; i2 < s2.length; i2++) {
|
|
1934
|
-
const ch = s2[i2];
|
|
1935
|
-
const isWs = /\s/.test(ch);
|
|
1936
|
-
if (isWs) {
|
|
1937
|
-
if (!inWs) {
|
|
1938
|
-
out += " ";
|
|
1939
|
-
inWs = true;
|
|
1940
|
-
}
|
|
1941
|
-
} else {
|
|
1942
|
-
out += ch;
|
|
1943
|
-
inWs = false;
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
return out;
|
|
1947
|
-
}
|
|
1948
|
-
function removeRedundantStaticTextChildren(parent, children) {
|
|
1949
|
-
if (!parent.name) return children;
|
|
1950
|
-
const parentNorm = normaliseSpaces(parent.name).trim();
|
|
1951
|
-
let combined = "";
|
|
1952
|
-
for (const c of children) {
|
|
1953
|
-
if (c.role === "StaticText" && c.name) {
|
|
1954
|
-
combined += normaliseSpaces(c.name).trim();
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
if (combined === parentNorm) {
|
|
1958
|
-
return children.filter((c) => c.role !== "StaticText");
|
|
1959
|
-
}
|
|
1960
|
-
return children;
|
|
1961
|
-
}
|
|
1962
|
-
function findNodeByBackendId(root, backendNodeId) {
|
|
1963
|
-
const stack = [root];
|
|
1964
|
-
while (stack.length) {
|
|
1965
|
-
const n = stack.pop();
|
|
1966
|
-
if (n.backendNodeId === backendNodeId) return n;
|
|
1967
|
-
if (n.children) for (const c of n.children) stack.push(c);
|
|
1968
|
-
if (n.shadowRoots) for (const s2 of n.shadowRoots) stack.push(s2);
|
|
1969
|
-
}
|
|
1970
|
-
return void 0;
|
|
1971
|
-
}
|
|
1972
1070
|
function injectSubtrees(rootOutline, idToTree) {
|
|
1973
1071
|
var _a4, _b;
|
|
1974
1072
|
const out = [];
|
|
@@ -2024,29 +1122,1069 @@ function diffCombinedTrees(prevTree, nextTree) {
|
|
|
2024
1122
|
);
|
|
2025
1123
|
return out.join("\n");
|
|
2026
1124
|
}
|
|
2027
|
-
function
|
|
2028
|
-
|
|
1125
|
+
function cleanText(input) {
|
|
1126
|
+
const PUA_START = 57344;
|
|
1127
|
+
const PUA_END = 63743;
|
|
1128
|
+
const NBSP = /* @__PURE__ */ new Set([160, 8239, 8199, 65279]);
|
|
1129
|
+
let out = "";
|
|
1130
|
+
let prevSpace = false;
|
|
1131
|
+
for (let i2 = 0; i2 < input.length; i2++) {
|
|
1132
|
+
const code = input.charCodeAt(i2);
|
|
1133
|
+
if (code >= PUA_START && code <= PUA_END) continue;
|
|
1134
|
+
if (NBSP.has(code)) {
|
|
1135
|
+
if (!prevSpace) {
|
|
1136
|
+
out += " ";
|
|
1137
|
+
prevSpace = true;
|
|
1138
|
+
}
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
out += input[i2];
|
|
1142
|
+
prevSpace = input[i2] === " ";
|
|
1143
|
+
}
|
|
1144
|
+
return out.trim();
|
|
2029
1145
|
}
|
|
2030
|
-
function
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
1146
|
+
function normaliseSpaces(s2) {
|
|
1147
|
+
let out = "";
|
|
1148
|
+
let inWs = false;
|
|
1149
|
+
for (let i2 = 0; i2 < s2.length; i2++) {
|
|
1150
|
+
const ch = s2[i2];
|
|
1151
|
+
const isWs = /\s/.test(ch);
|
|
1152
|
+
if (isWs) {
|
|
1153
|
+
if (!inWs) {
|
|
1154
|
+
out += " ";
|
|
1155
|
+
inWs = true;
|
|
1156
|
+
}
|
|
1157
|
+
} else {
|
|
1158
|
+
out += ch;
|
|
1159
|
+
inWs = false;
|
|
1160
|
+
}
|
|
2035
1161
|
}
|
|
2036
|
-
return
|
|
1162
|
+
return out;
|
|
2037
1163
|
}
|
|
2038
|
-
var
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
1164
|
+
var init_treeFormatUtils = __esm({
|
|
1165
|
+
"lib/v3/understudy/a11y/snapshot/treeFormatUtils.ts"() {
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1169
|
+
// lib/v3/understudy/a11y/snapshot/a11yTree.ts
|
|
1170
|
+
function a11yForFrame(session, frameId, opts) {
|
|
1171
|
+
return __async(this, null, function* () {
|
|
1172
|
+
var _a4, _b;
|
|
1173
|
+
yield session.send("Accessibility.enable").catch(() => {
|
|
1174
|
+
});
|
|
1175
|
+
yield session.send("Runtime.enable").catch(() => {
|
|
1176
|
+
});
|
|
1177
|
+
yield session.send("DOM.enable").catch(() => {
|
|
1178
|
+
});
|
|
1179
|
+
let nodes = [];
|
|
1180
|
+
try {
|
|
1181
|
+
const params = frameId ? { frameId } : {};
|
|
1182
|
+
({ nodes } = yield session.send("Accessibility.getFullAXTree", params));
|
|
1183
|
+
} catch (e2) {
|
|
1184
|
+
const msg = String((_b = (_a4 = e2 == null ? void 0 : e2.message) != null ? _a4 : e2) != null ? _b : "");
|
|
1185
|
+
const isFrameScopeError = msg.includes("Frame with the given") || msg.includes("does not belong to the target") || msg.includes("is not found");
|
|
1186
|
+
if (!isFrameScopeError || !frameId) throw e2;
|
|
1187
|
+
({ nodes } = yield session.send("Accessibility.getFullAXTree"));
|
|
1188
|
+
}
|
|
1189
|
+
const urlMap = {};
|
|
1190
|
+
for (const n of nodes) {
|
|
1191
|
+
const be = n.backendDOMNodeId;
|
|
1192
|
+
if (typeof be !== "number") continue;
|
|
1193
|
+
const url = extractUrlFromAXNode(n);
|
|
1194
|
+
if (!url) continue;
|
|
1195
|
+
const enc = opts.encode(be);
|
|
1196
|
+
urlMap[enc] = url;
|
|
1197
|
+
}
|
|
1198
|
+
let scopeApplied = false;
|
|
1199
|
+
const nodesForOutline = yield (() => __async(null, null, function* () {
|
|
1200
|
+
var _a5, _b2, _c;
|
|
1201
|
+
const sel = (_a5 = opts.focusSelector) == null ? void 0 : _a5.trim();
|
|
1202
|
+
if (!sel) return nodes;
|
|
1203
|
+
try {
|
|
1204
|
+
const looksLikeXPath = /^xpath=/i.test(sel) || sel.startsWith("/");
|
|
1205
|
+
const objectId = looksLikeXPath ? yield resolveObjectIdForXPath(session, sel, frameId) : yield resolveObjectIdForCss(session, sel, frameId);
|
|
1206
|
+
if (!objectId) return nodes;
|
|
1207
|
+
const desc = yield session.send(
|
|
1208
|
+
"DOM.describeNode",
|
|
1209
|
+
{ objectId }
|
|
1210
|
+
);
|
|
1211
|
+
const be = (_b2 = desc.node) == null ? void 0 : _b2.backendNodeId;
|
|
1212
|
+
if (typeof be !== "number") return nodes;
|
|
1213
|
+
const target = nodes.find((n) => n.backendDOMNodeId === be);
|
|
1214
|
+
if (!target) return nodes;
|
|
1215
|
+
scopeApplied = true;
|
|
1216
|
+
const keep = /* @__PURE__ */ new Set([target.nodeId]);
|
|
1217
|
+
const queue = [target];
|
|
1218
|
+
while (queue.length) {
|
|
1219
|
+
const cur = queue.shift();
|
|
1220
|
+
for (const id of (_c = cur.childIds) != null ? _c : []) {
|
|
1221
|
+
if (keep.has(id)) continue;
|
|
1222
|
+
keep.add(id);
|
|
1223
|
+
const child = nodes.find((n) => n.nodeId === id);
|
|
1224
|
+
if (child) queue.push(child);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
return nodes.filter((n) => keep.has(n.nodeId)).map(
|
|
1228
|
+
(n) => n.nodeId === target.nodeId ? __spreadProps(__spreadValues({}, n), { parentId: void 0 }) : n
|
|
1229
|
+
);
|
|
1230
|
+
} catch (e2) {
|
|
1231
|
+
return nodes;
|
|
1232
|
+
}
|
|
1233
|
+
}))();
|
|
1234
|
+
const decorated = decorateRoles(nodesForOutline, opts);
|
|
1235
|
+
const { tree } = yield buildHierarchicalTree(decorated, opts);
|
|
1236
|
+
const simplified = tree.map((n) => formatTreeLine(n)).join("\n");
|
|
1237
|
+
return { outline: simplified.trimEnd(), urlMap, scopeApplied };
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
function decorateRoles(nodes, opts) {
|
|
1241
|
+
const asRole = (n) => {
|
|
1242
|
+
var _a4, _b;
|
|
1243
|
+
return String((_b = (_a4 = n.role) == null ? void 0 : _a4.value) != null ? _b : "");
|
|
1244
|
+
};
|
|
1245
|
+
return nodes.map((n) => {
|
|
1246
|
+
var _a4, _b, _c;
|
|
1247
|
+
let encodedId;
|
|
1248
|
+
if (typeof n.backendDOMNodeId === "number") {
|
|
1249
|
+
try {
|
|
1250
|
+
encodedId = opts.encode(n.backendDOMNodeId);
|
|
1251
|
+
} catch (e2) {
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
let role = asRole(n);
|
|
1255
|
+
const domIsScrollable = encodedId ? opts.scrollableMap[encodedId] === true : false;
|
|
1256
|
+
const tag = encodedId ? opts.tagNameMap[encodedId] : void 0;
|
|
1257
|
+
const isHtmlElement = tag === "html";
|
|
1258
|
+
if ((domIsScrollable || isHtmlElement) && tag !== "#document") {
|
|
1259
|
+
const tagLabel = tag && tag.startsWith("#") ? tag.slice(1) : tag;
|
|
1260
|
+
role = tagLabel ? `scrollable, ${tagLabel}` : `scrollable${role ? `, ${role}` : ""}`;
|
|
1261
|
+
}
|
|
1262
|
+
return {
|
|
1263
|
+
role,
|
|
1264
|
+
name: (_a4 = n.name) == null ? void 0 : _a4.value,
|
|
1265
|
+
description: (_b = n.description) == null ? void 0 : _b.value,
|
|
1266
|
+
value: (_c = n.value) == null ? void 0 : _c.value,
|
|
1267
|
+
nodeId: n.nodeId,
|
|
1268
|
+
backendDOMNodeId: n.backendDOMNodeId,
|
|
1269
|
+
parentId: n.parentId,
|
|
1270
|
+
childIds: n.childIds,
|
|
1271
|
+
encodedId
|
|
1272
|
+
};
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
function buildHierarchicalTree(nodes, opts) {
|
|
1276
|
+
return __async(this, null, function* () {
|
|
1277
|
+
var _a4;
|
|
1278
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
1279
|
+
for (const n of nodes) {
|
|
1280
|
+
const keep = !!(n.name && n.name.trim()) || !!(n.childIds && n.childIds.length) || !isStructural(n.role);
|
|
1281
|
+
if (!keep) continue;
|
|
1282
|
+
nodeMap.set(n.nodeId, __spreadValues({}, n));
|
|
1283
|
+
}
|
|
1284
|
+
for (const n of nodes) {
|
|
1285
|
+
if (!n.parentId) continue;
|
|
1286
|
+
const parent = nodeMap.get(n.parentId);
|
|
1287
|
+
const cur = nodeMap.get(n.nodeId);
|
|
1288
|
+
if (parent && cur) ((_a4 = parent.children) != null ? _a4 : parent.children = []).push(cur);
|
|
1289
|
+
}
|
|
1290
|
+
const roots = nodes.filter((n) => !n.parentId && nodeMap.has(n.nodeId)).map((n) => nodeMap.get(n.nodeId));
|
|
1291
|
+
const cleaned = (yield Promise.all(roots.map(pruneStructuralSafe))).filter(
|
|
1292
|
+
Boolean
|
|
1293
|
+
);
|
|
1294
|
+
return { tree: cleaned };
|
|
1295
|
+
function pruneStructuralSafe(node) {
|
|
1296
|
+
return __async(this, null, function* () {
|
|
1297
|
+
var _a5;
|
|
1298
|
+
if (+node.nodeId < 0) return null;
|
|
1299
|
+
const children = (_a5 = node.children) != null ? _a5 : [];
|
|
1300
|
+
if (!children.length) {
|
|
1301
|
+
return isStructural(node.role) ? null : node;
|
|
1302
|
+
}
|
|
1303
|
+
const cleanedKids = (yield Promise.all(children.map(pruneStructuralSafe))).filter(Boolean);
|
|
1304
|
+
const prunedStatic = removeRedundantStaticTextChildren(node, cleanedKids);
|
|
1305
|
+
if (isStructural(node.role)) {
|
|
1306
|
+
if (prunedStatic.length === 1) return prunedStatic[0];
|
|
1307
|
+
if (prunedStatic.length === 0) return null;
|
|
1308
|
+
}
|
|
1309
|
+
let newRole = node.role;
|
|
1310
|
+
if ((newRole === "generic" || newRole === "none") && node.encodedId) {
|
|
1311
|
+
const tagName = opts.tagNameMap[node.encodedId];
|
|
1312
|
+
if (tagName) newRole = tagName;
|
|
1313
|
+
}
|
|
1314
|
+
if (newRole === "combobox" && node.encodedId) {
|
|
1315
|
+
const tagName = opts.tagNameMap[node.encodedId];
|
|
1316
|
+
if (tagName === "select") newRole = "select";
|
|
1317
|
+
}
|
|
1318
|
+
return __spreadProps(__spreadValues({}, node), { role: newRole, children: prunedStatic });
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
function isStructural(role) {
|
|
1324
|
+
const r2 = role == null ? void 0 : role.toLowerCase();
|
|
1325
|
+
return r2 === "generic" || r2 === "none" || r2 === "inlinetextbox";
|
|
1326
|
+
}
|
|
1327
|
+
function extractUrlFromAXNode(ax) {
|
|
1328
|
+
var _a4, _b;
|
|
1329
|
+
const props = (_a4 = ax.properties) != null ? _a4 : [];
|
|
1330
|
+
const urlProp = props.find((p) => p.name === "url");
|
|
1331
|
+
const value = (_b = urlProp == null ? void 0 : urlProp.value) == null ? void 0 : _b.value;
|
|
1332
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1333
|
+
}
|
|
1334
|
+
function removeRedundantStaticTextChildren(parent, children) {
|
|
1335
|
+
if (!parent.name) return children;
|
|
1336
|
+
const parentNorm = normaliseSpaces(parent.name).trim();
|
|
1337
|
+
let combined = "";
|
|
1338
|
+
for (const c of children) {
|
|
1339
|
+
if (c.role === "StaticText" && c.name) {
|
|
1340
|
+
combined += normaliseSpaces(c.name).trim();
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (combined === parentNorm) {
|
|
1344
|
+
return children.filter((c) => c.role !== "StaticText");
|
|
1345
|
+
}
|
|
1346
|
+
return children;
|
|
1347
|
+
}
|
|
1348
|
+
var init_a11yTree = __esm({
|
|
1349
|
+
"lib/v3/understudy/a11y/snapshot/a11yTree.ts"() {
|
|
1350
|
+
init_focusSelectors();
|
|
1351
|
+
init_treeFormatUtils();
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
// lib/v3/understudy/a11y/snapshot/domTree.ts
|
|
1356
|
+
function isCborStackError(message) {
|
|
1357
|
+
return message.includes("CBOR: stack limit exceeded");
|
|
1358
|
+
}
|
|
1359
|
+
function shouldExpandNode(node) {
|
|
1360
|
+
var _a4, _b, _c;
|
|
1361
|
+
const declaredChildren = (_a4 = node.childNodeCount) != null ? _a4 : 0;
|
|
1362
|
+
const realizedChildren = (_c = (_b = node.children) == null ? void 0 : _b.length) != null ? _c : 0;
|
|
1363
|
+
return declaredChildren > realizedChildren;
|
|
1364
|
+
}
|
|
1365
|
+
function mergeDomNodes(target, source) {
|
|
1366
|
+
var _a4, _b, _c, _d2;
|
|
1367
|
+
target.childNodeCount = (_a4 = source.childNodeCount) != null ? _a4 : target.childNodeCount;
|
|
1368
|
+
target.children = (_b = source.children) != null ? _b : target.children;
|
|
1369
|
+
target.shadowRoots = (_c = source.shadowRoots) != null ? _c : target.shadowRoots;
|
|
1370
|
+
target.contentDocument = (_d2 = source.contentDocument) != null ? _d2 : target.contentDocument;
|
|
1371
|
+
}
|
|
1372
|
+
function collectDomTraversalTargets(node) {
|
|
1373
|
+
const targets = [];
|
|
1374
|
+
if (node.children) targets.push(...node.children);
|
|
1375
|
+
if (node.shadowRoots) targets.push(...node.shadowRoots);
|
|
1376
|
+
if (node.contentDocument) targets.push(node.contentDocument);
|
|
1377
|
+
return targets;
|
|
1378
|
+
}
|
|
1379
|
+
function hydrateDomTree(session, root, pierce) {
|
|
1380
|
+
return __async(this, null, function* () {
|
|
1381
|
+
var _a4, _b;
|
|
1382
|
+
const stack = [root];
|
|
1383
|
+
const expandedNodeIds = /* @__PURE__ */ new Set();
|
|
1384
|
+
const expandedBackendIds = /* @__PURE__ */ new Set();
|
|
1385
|
+
while (stack.length) {
|
|
1386
|
+
const node = stack.pop();
|
|
1387
|
+
const nodeId = typeof node.nodeId === "number" && node.nodeId > 0 ? node.nodeId : void 0;
|
|
1388
|
+
const backendId = typeof node.backendNodeId === "number" && node.backendNodeId > 0 ? node.backendNodeId : void 0;
|
|
1389
|
+
const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;
|
|
1390
|
+
const seenByBackend = !nodeId && backendId ? expandedBackendIds.has(backendId) : false;
|
|
1391
|
+
if (seenByNode || seenByBackend) continue;
|
|
1392
|
+
if (nodeId) expandedNodeIds.add(nodeId);
|
|
1393
|
+
else if (backendId) expandedBackendIds.add(backendId);
|
|
1394
|
+
const needsExpansion = shouldExpandNode(node);
|
|
1395
|
+
if (needsExpansion && (nodeId || backendId)) {
|
|
1396
|
+
const describeParamsBase = nodeId ? { nodeId } : { backendNodeId: backendId };
|
|
1397
|
+
let expanded = false;
|
|
1398
|
+
for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {
|
|
1399
|
+
try {
|
|
1400
|
+
const described = yield session.send(
|
|
1401
|
+
"DOM.describeNode",
|
|
1402
|
+
__spreadProps(__spreadValues({}, describeParamsBase), {
|
|
1403
|
+
depth,
|
|
1404
|
+
pierce
|
|
1405
|
+
})
|
|
1406
|
+
);
|
|
1407
|
+
mergeDomNodes(node, described.node);
|
|
1408
|
+
if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {
|
|
1409
|
+
node.nodeId = described.node.nodeId;
|
|
1410
|
+
expandedNodeIds.add(described.node.nodeId);
|
|
1411
|
+
}
|
|
1412
|
+
expanded = true;
|
|
1413
|
+
break;
|
|
1414
|
+
} catch (err) {
|
|
1415
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1416
|
+
if (isCborStackError(message)) {
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1419
|
+
const identifier = (_a4 = nodeId != null ? nodeId : backendId) != null ? _a4 : "unknown";
|
|
1420
|
+
throw new StagehandDomProcessError(
|
|
1421
|
+
`Failed to expand DOM node ${identifier}: ${String(err)}`
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
if (!expanded) {
|
|
1426
|
+
const identifier = (_b = nodeId != null ? nodeId : backendId) != null ? _b : "unknown";
|
|
1427
|
+
throw new StagehandDomProcessError(
|
|
1428
|
+
`Unable to expand DOM node ${identifier} after describeNode depth retries`
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
for (const child of collectDomTraversalTargets(node)) {
|
|
1433
|
+
stack.push(child);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
function getDomTreeWithFallback(session, pierce) {
|
|
1439
|
+
return __async(this, null, function* () {
|
|
1440
|
+
let lastCborMessage = "";
|
|
1441
|
+
for (const depth of DOM_DEPTH_ATTEMPTS) {
|
|
1442
|
+
try {
|
|
1443
|
+
const { root } = yield session.send(
|
|
1444
|
+
"DOM.getDocument",
|
|
1445
|
+
{ depth, pierce }
|
|
1446
|
+
);
|
|
1447
|
+
if (depth !== -1) {
|
|
1448
|
+
yield hydrateDomTree(session, root, pierce);
|
|
1449
|
+
}
|
|
1450
|
+
return root;
|
|
1451
|
+
} catch (err) {
|
|
1452
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1453
|
+
if (isCborStackError(message)) {
|
|
1454
|
+
lastCborMessage = message;
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
throw err;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
throw new StagehandDomProcessError(
|
|
1461
|
+
lastCborMessage ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}` : "CDP DOM.getDocument failed after adaptive depth retries."
|
|
1462
|
+
);
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
function domMapsForSession(session, frameId, pierce, encode, attemptOwnerLookup = true) {
|
|
1466
|
+
return __async(this, null, function* () {
|
|
1467
|
+
var _a4, _b;
|
|
1468
|
+
yield session.send("DOM.enable").catch(() => {
|
|
1469
|
+
});
|
|
1470
|
+
const root = yield getDomTreeWithFallback(session, pierce);
|
|
1471
|
+
let startNode = root;
|
|
1472
|
+
if (attemptOwnerLookup) {
|
|
1473
|
+
try {
|
|
1474
|
+
const owner = yield session.send(
|
|
1475
|
+
"DOM.getFrameOwner",
|
|
1476
|
+
{ frameId }
|
|
1477
|
+
);
|
|
1478
|
+
const ownerBackendId = owner.backendNodeId;
|
|
1479
|
+
if (typeof ownerBackendId === "number") {
|
|
1480
|
+
const ownerEl = findNodeByBackendId(root, ownerBackendId);
|
|
1481
|
+
if (ownerEl == null ? void 0 : ownerEl.contentDocument) {
|
|
1482
|
+
startNode = ownerEl.contentDocument;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
} catch (e2) {
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
const tagNameMap = {};
|
|
1489
|
+
const xpathMap = {};
|
|
1490
|
+
const scrollableMap = {};
|
|
1491
|
+
const stack = [{ node: startNode, xpath: "" }];
|
|
1492
|
+
while (stack.length) {
|
|
1493
|
+
const { node, xpath } = stack.pop();
|
|
1494
|
+
if (node.backendNodeId) {
|
|
1495
|
+
const encId = encode(frameId, node.backendNodeId);
|
|
1496
|
+
tagNameMap[encId] = String(node.nodeName).toLowerCase();
|
|
1497
|
+
xpathMap[encId] = xpath || "/";
|
|
1498
|
+
const isScrollable = (node == null ? void 0 : node.isScrollable) === true;
|
|
1499
|
+
if (isScrollable) scrollableMap[encId] = true;
|
|
1500
|
+
}
|
|
1501
|
+
const kids = (_a4 = node.children) != null ? _a4 : [];
|
|
1502
|
+
if (kids.length) {
|
|
1503
|
+
const segs = buildChildXPathSegments(kids);
|
|
1504
|
+
for (let i2 = kids.length - 1; i2 >= 0; i2--) {
|
|
1505
|
+
const child = kids[i2];
|
|
1506
|
+
const step = segs[i2];
|
|
1507
|
+
stack.push({
|
|
1508
|
+
node: child,
|
|
1509
|
+
xpath: joinXPath(xpath, step)
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
for (const sr of (_b = node.shadowRoots) != null ? _b : []) {
|
|
1514
|
+
stack.push({
|
|
1515
|
+
node: sr,
|
|
1516
|
+
xpath: joinXPath(xpath, "//")
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return { tagNameMap, xpathMap, scrollableMap };
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
function buildSessionDomIndex(session, pierce) {
|
|
1524
|
+
return __async(this, null, function* () {
|
|
1525
|
+
var _a4, _b;
|
|
1526
|
+
yield session.send("DOM.enable").catch(() => {
|
|
1527
|
+
});
|
|
1528
|
+
const root = yield getDomTreeWithFallback(session, pierce);
|
|
1529
|
+
const absByBe = /* @__PURE__ */ new Map();
|
|
1530
|
+
const tagByBe = /* @__PURE__ */ new Map();
|
|
1531
|
+
const scrollByBe = /* @__PURE__ */ new Map();
|
|
1532
|
+
const docRootOf = /* @__PURE__ */ new Map();
|
|
1533
|
+
const contentDocRootByIframe = /* @__PURE__ */ new Map();
|
|
1534
|
+
const rootBe = root.backendNodeId;
|
|
1535
|
+
const stack = [{ node: root, xp: "/", docRootBe: rootBe }];
|
|
1536
|
+
while (stack.length) {
|
|
1537
|
+
const { node, xp, docRootBe } = stack.pop();
|
|
1538
|
+
if (node.backendNodeId) {
|
|
1539
|
+
absByBe.set(node.backendNodeId, xp || "/");
|
|
1540
|
+
tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());
|
|
1541
|
+
if ((node == null ? void 0 : node.isScrollable) === true) scrollByBe.set(node.backendNodeId, true);
|
|
1542
|
+
docRootOf.set(node.backendNodeId, docRootBe);
|
|
1543
|
+
}
|
|
1544
|
+
const kids = (_a4 = node.children) != null ? _a4 : [];
|
|
1545
|
+
if (kids.length) {
|
|
1546
|
+
const segs = buildChildXPathSegments(kids);
|
|
1547
|
+
for (let i2 = kids.length - 1; i2 >= 0; i2--) {
|
|
1548
|
+
const child = kids[i2];
|
|
1549
|
+
const step = segs[i2];
|
|
1550
|
+
stack.push({ node: child, xp: joinXPath(xp, step), docRootBe });
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
for (const sr of (_b = node.shadowRoots) != null ? _b : []) {
|
|
1554
|
+
stack.push({ node: sr, xp: joinXPath(xp, "//"), docRootBe });
|
|
1555
|
+
}
|
|
1556
|
+
const cd = node.contentDocument;
|
|
1557
|
+
if (cd && typeof cd.backendNodeId === "number") {
|
|
1558
|
+
contentDocRootByIframe.set(node.backendNodeId, cd.backendNodeId);
|
|
1559
|
+
stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
return {
|
|
1563
|
+
rootBackend: rootBe,
|
|
1564
|
+
absByBe,
|
|
1565
|
+
tagByBe,
|
|
1566
|
+
scrollByBe,
|
|
1567
|
+
docRootOf,
|
|
1568
|
+
contentDocRootByIframe
|
|
1569
|
+
};
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
function relativizeXPath(baseAbs, nodeAbs) {
|
|
1573
|
+
const base = normalizeXPath(baseAbs);
|
|
1574
|
+
const abs = normalizeXPath(nodeAbs);
|
|
1575
|
+
if (abs === base) return "/";
|
|
1576
|
+
if (abs.startsWith(base)) {
|
|
1577
|
+
const tail = abs.slice(base.length);
|
|
1578
|
+
if (!tail) return "/";
|
|
1579
|
+
return tail.startsWith("/") || tail.startsWith("//") ? tail : `/${tail}`;
|
|
1580
|
+
}
|
|
1581
|
+
if (base === "/") return abs;
|
|
1582
|
+
return abs;
|
|
1583
|
+
}
|
|
1584
|
+
function findNodeByBackendId(root, backendNodeId) {
|
|
1585
|
+
const stack = [root];
|
|
1586
|
+
while (stack.length) {
|
|
1587
|
+
const n = stack.pop();
|
|
1588
|
+
if (n.backendNodeId === backendNodeId) return n;
|
|
1589
|
+
if (n.children) for (const c of n.children) stack.push(c);
|
|
1590
|
+
if (n.shadowRoots) for (const s2 of n.shadowRoots) stack.push(s2);
|
|
1591
|
+
}
|
|
1592
|
+
return void 0;
|
|
1593
|
+
}
|
|
1594
|
+
var DOM_DEPTH_ATTEMPTS, DESCRIBE_DEPTH_ATTEMPTS;
|
|
1595
|
+
var init_domTree = __esm({
|
|
1596
|
+
"lib/v3/understudy/a11y/snapshot/domTree.ts"() {
|
|
1597
|
+
init_sdkErrors();
|
|
1598
|
+
init_xpathUtils();
|
|
1599
|
+
DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];
|
|
1600
|
+
DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
|
|
1604
|
+
// lib/v3/understudy/a11y/snapshot/sessions.ts
|
|
1605
|
+
function ownerSession(page, frameId) {
|
|
1606
|
+
return page.getSessionForFrame(frameId);
|
|
1607
|
+
}
|
|
1608
|
+
function parentSession(page, parentByFrame, frameId) {
|
|
1609
|
+
var _a4;
|
|
1610
|
+
const parentId = (_a4 = parentByFrame.get(frameId)) != null ? _a4 : null;
|
|
1611
|
+
if (!parentId) {
|
|
1612
|
+
return page.getSessionForFrame(frameId);
|
|
1613
|
+
}
|
|
1614
|
+
return page.getSessionForFrame(parentId);
|
|
1615
|
+
}
|
|
1616
|
+
var init_sessions = __esm({
|
|
1617
|
+
"lib/v3/understudy/a11y/snapshot/sessions.ts"() {
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
// lib/v3/understudy/a11y/snapshot/capture.ts
|
|
1622
|
+
function captureHybridSnapshot(page, options) {
|
|
1623
|
+
return __async(this, null, function* () {
|
|
1624
|
+
var _a4;
|
|
1625
|
+
const pierce = (_a4 = options == null ? void 0 : options.pierceShadow) != null ? _a4 : true;
|
|
1626
|
+
const context = buildFrameContext(page);
|
|
1627
|
+
const scopedSnapshot = yield tryScopedSnapshot(
|
|
1628
|
+
page,
|
|
1629
|
+
options,
|
|
1630
|
+
context,
|
|
1631
|
+
pierce
|
|
1632
|
+
);
|
|
1633
|
+
if (scopedSnapshot) return scopedSnapshot;
|
|
1634
|
+
const sessionToIndex = yield buildSessionIndexes(
|
|
1635
|
+
page,
|
|
1636
|
+
context.frames,
|
|
1637
|
+
pierce
|
|
1638
|
+
);
|
|
1639
|
+
const { perFrameMaps, perFrameOutlines } = yield collectPerFrameMaps(
|
|
1640
|
+
page,
|
|
1641
|
+
context,
|
|
1642
|
+
sessionToIndex,
|
|
1643
|
+
options,
|
|
1644
|
+
pierce
|
|
1645
|
+
);
|
|
1646
|
+
const { absPrefix, iframeHostEncByChild } = yield computeFramePrefixes(
|
|
1647
|
+
page,
|
|
1648
|
+
context,
|
|
1649
|
+
perFrameMaps
|
|
1650
|
+
);
|
|
1651
|
+
return mergeFramesIntoSnapshot(
|
|
1652
|
+
context,
|
|
1653
|
+
perFrameMaps,
|
|
1654
|
+
perFrameOutlines,
|
|
1655
|
+
absPrefix,
|
|
1656
|
+
iframeHostEncByChild
|
|
1657
|
+
);
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
function buildFrameContext(page) {
|
|
1661
|
+
const rootId = page.mainFrameId();
|
|
1662
|
+
const frameTree = page.asProtocolFrameTree(rootId);
|
|
1663
|
+
const parentByFrame = /* @__PURE__ */ new Map();
|
|
1664
|
+
(function index(n, parent) {
|
|
1665
|
+
var _a4;
|
|
1666
|
+
parentByFrame.set(n.frame.id, parent);
|
|
1667
|
+
for (const c of (_a4 = n.childFrames) != null ? _a4 : []) index(c, n.frame.id);
|
|
1668
|
+
})(frameTree, null);
|
|
1669
|
+
const frames = page.listAllFrameIds();
|
|
1670
|
+
return { rootId, parentByFrame, frames };
|
|
1671
|
+
}
|
|
1672
|
+
function tryScopedSnapshot(page, options, context, pierce) {
|
|
1673
|
+
return __async(this, null, function* () {
|
|
1674
|
+
var _a4, _b;
|
|
1675
|
+
const requestedFocus = (_a4 = options == null ? void 0 : options.focusSelector) == null ? void 0 : _a4.trim();
|
|
1676
|
+
if (!requestedFocus) return null;
|
|
1677
|
+
const logScopeFallback = () => {
|
|
1678
|
+
var _a5;
|
|
1679
|
+
v3Logger({
|
|
1680
|
+
message: `Unable to narrow scope with selector. Falling back to using full DOM`,
|
|
1681
|
+
level: 1,
|
|
1682
|
+
auxiliary: {
|
|
1683
|
+
arguments: {
|
|
1684
|
+
value: `selector: ${(_a5 = options == null ? void 0 : options.focusSelector) == null ? void 0 : _a5.trim()}`,
|
|
1685
|
+
type: "string"
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
1689
|
+
};
|
|
1690
|
+
try {
|
|
1691
|
+
let targetFrameId;
|
|
1692
|
+
let tailSelector;
|
|
1693
|
+
let absPrefix;
|
|
1694
|
+
const looksLikeXPath = /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith("/");
|
|
1695
|
+
if (looksLikeXPath) {
|
|
1696
|
+
const focus = normalizeXPath(requestedFocus);
|
|
1697
|
+
const hit = yield resolveFocusFrameAndTail(
|
|
1698
|
+
page,
|
|
1699
|
+
focus,
|
|
1700
|
+
context.parentByFrame,
|
|
1701
|
+
context.rootId
|
|
1702
|
+
);
|
|
1703
|
+
targetFrameId = hit.targetFrameId;
|
|
1704
|
+
tailSelector = hit.tailXPath || void 0;
|
|
1705
|
+
absPrefix = hit.absPrefix;
|
|
1706
|
+
} else {
|
|
1707
|
+
const cssHit = yield resolveCssFocusFrameAndTail(
|
|
1708
|
+
page,
|
|
1709
|
+
requestedFocus,
|
|
1710
|
+
context.parentByFrame,
|
|
1711
|
+
context.rootId
|
|
1712
|
+
);
|
|
1713
|
+
targetFrameId = cssHit.targetFrameId;
|
|
1714
|
+
tailSelector = cssHit.tailSelector || void 0;
|
|
1715
|
+
absPrefix = cssHit.absPrefix;
|
|
1716
|
+
}
|
|
1717
|
+
const owningSess = ownerSession(page, targetFrameId);
|
|
1718
|
+
const parentId = context.parentByFrame.get(targetFrameId);
|
|
1719
|
+
const sameSessionAsParent = !!parentId && ownerSession(page, parentId) === ownerSession(page, targetFrameId);
|
|
1720
|
+
const { tagNameMap, xpathMap, scrollableMap } = yield domMapsForSession(
|
|
1721
|
+
owningSess,
|
|
1722
|
+
targetFrameId,
|
|
1723
|
+
pierce,
|
|
1724
|
+
(fid, be) => `${page.getOrdinal(fid)}-${be}`,
|
|
1725
|
+
sameSessionAsParent
|
|
1726
|
+
);
|
|
1727
|
+
const { outline, urlMap, scopeApplied } = yield a11yForFrame(
|
|
1728
|
+
owningSess,
|
|
1729
|
+
targetFrameId,
|
|
1730
|
+
{
|
|
1731
|
+
focusSelector: tailSelector || void 0,
|
|
1732
|
+
tagNameMap,
|
|
1733
|
+
experimental: (_b = options == null ? void 0 : options.experimental) != null ? _b : false,
|
|
1734
|
+
scrollableMap,
|
|
1735
|
+
encode: (backendNodeId) => `${page.getOrdinal(targetFrameId)}-${backendNodeId}`
|
|
1736
|
+
}
|
|
1737
|
+
);
|
|
1738
|
+
const scopedXpathMap = {};
|
|
1739
|
+
const abs = absPrefix != null ? absPrefix : "";
|
|
1740
|
+
const isRoot = !abs || abs === "/";
|
|
1741
|
+
if (isRoot) {
|
|
1742
|
+
Object.assign(scopedXpathMap, xpathMap);
|
|
1743
|
+
} else {
|
|
1744
|
+
for (const [encId, xp] of Object.entries(xpathMap)) {
|
|
1745
|
+
scopedXpathMap[encId] = prefixXPath(abs, xp);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
const scopedUrlMap = __spreadValues({}, urlMap);
|
|
1749
|
+
const snapshot = {
|
|
1750
|
+
combinedTree: outline,
|
|
1751
|
+
combinedXpathMap: scopedXpathMap,
|
|
1752
|
+
combinedUrlMap: scopedUrlMap,
|
|
1753
|
+
perFrame: [
|
|
1754
|
+
{
|
|
1755
|
+
frameId: targetFrameId,
|
|
1756
|
+
outline,
|
|
1757
|
+
xpathMap,
|
|
1758
|
+
urlMap
|
|
1759
|
+
}
|
|
1760
|
+
]
|
|
1761
|
+
};
|
|
1762
|
+
if (scopeApplied) {
|
|
1763
|
+
return snapshot;
|
|
1764
|
+
}
|
|
1765
|
+
logScopeFallback();
|
|
1766
|
+
} catch (e2) {
|
|
1767
|
+
logScopeFallback();
|
|
1768
|
+
}
|
|
1769
|
+
return null;
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
function buildSessionIndexes(page, frames, pierce) {
|
|
1773
|
+
return __async(this, null, function* () {
|
|
1774
|
+
var _a4;
|
|
1775
|
+
const sessionToIndex = /* @__PURE__ */ new Map();
|
|
1776
|
+
const sessionById = /* @__PURE__ */ new Map();
|
|
1777
|
+
for (const frameId of frames) {
|
|
1778
|
+
const sess = ownerSession(page, frameId);
|
|
1779
|
+
const sid = (_a4 = sess.id) != null ? _a4 : "root";
|
|
1780
|
+
if (!sessionById.has(sid)) sessionById.set(sid, sess);
|
|
1781
|
+
}
|
|
1782
|
+
for (const [sid, sess] of sessionById.entries()) {
|
|
1783
|
+
const idx = yield buildSessionDomIndex(sess, pierce);
|
|
1784
|
+
sessionToIndex.set(sid, idx);
|
|
1785
|
+
}
|
|
1786
|
+
return sessionToIndex;
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
function collectPerFrameMaps(page, context, sessionToIndex, options, pierce) {
|
|
1790
|
+
return __async(this, null, function* () {
|
|
1791
|
+
var _a4, _b, _c;
|
|
1792
|
+
const perFrameMaps = /* @__PURE__ */ new Map();
|
|
1793
|
+
const perFrameOutlines = [];
|
|
1794
|
+
for (const frameId of context.frames) {
|
|
1795
|
+
const sess = ownerSession(page, frameId);
|
|
1796
|
+
const sid = (_a4 = sess.id) != null ? _a4 : "root";
|
|
1797
|
+
let idx = sessionToIndex.get(sid);
|
|
1798
|
+
if (!idx) {
|
|
1799
|
+
idx = yield buildSessionDomIndex(sess, pierce);
|
|
1800
|
+
sessionToIndex.set(sid, idx);
|
|
1801
|
+
}
|
|
1802
|
+
const parentId = context.parentByFrame.get(frameId);
|
|
1803
|
+
const sameSessionAsParent = !!parentId && ownerSession(page, parentId) === sess;
|
|
1804
|
+
let docRootBe = idx.rootBackend;
|
|
1805
|
+
if (sameSessionAsParent) {
|
|
1806
|
+
try {
|
|
1807
|
+
const { backendNodeId } = yield sess.send(
|
|
1808
|
+
"DOM.getFrameOwner",
|
|
1809
|
+
{ frameId }
|
|
1810
|
+
);
|
|
1811
|
+
if (typeof backendNodeId === "number") {
|
|
1812
|
+
const cdBe = idx.contentDocRootByIframe.get(backendNodeId);
|
|
1813
|
+
if (typeof cdBe === "number") docRootBe = cdBe;
|
|
1814
|
+
}
|
|
1815
|
+
} catch (e2) {
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
const tagNameMap = {};
|
|
1819
|
+
const xpathMap = {};
|
|
1820
|
+
const scrollableMap = {};
|
|
1821
|
+
const enc = (be) => `${page.getOrdinal(frameId)}-${be}`;
|
|
1822
|
+
const baseAbs = (_b = idx.absByBe.get(docRootBe)) != null ? _b : "/";
|
|
1823
|
+
for (const [be, nodeAbs] of idx.absByBe.entries()) {
|
|
1824
|
+
const nodeDocRoot = idx.docRootOf.get(be);
|
|
1825
|
+
if (nodeDocRoot !== docRootBe) continue;
|
|
1826
|
+
const rel = relativizeXPath(baseAbs, nodeAbs);
|
|
1827
|
+
const key = enc(be);
|
|
1828
|
+
xpathMap[key] = rel;
|
|
1829
|
+
const tag = idx.tagByBe.get(be);
|
|
1830
|
+
if (tag) tagNameMap[key] = tag;
|
|
1831
|
+
if (idx.scrollByBe.get(be)) scrollableMap[key] = true;
|
|
1832
|
+
}
|
|
1833
|
+
const { outline, urlMap } = yield a11yForFrame(sess, frameId, {
|
|
1834
|
+
experimental: (_c = options == null ? void 0 : options.experimental) != null ? _c : false,
|
|
1835
|
+
tagNameMap,
|
|
1836
|
+
scrollableMap,
|
|
1837
|
+
encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`
|
|
1838
|
+
});
|
|
1839
|
+
perFrameOutlines.push({ frameId, outline });
|
|
1840
|
+
perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });
|
|
1841
|
+
}
|
|
1842
|
+
return { perFrameMaps, perFrameOutlines };
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
function computeFramePrefixes(page, context, perFrameMaps) {
|
|
1846
|
+
return __async(this, null, function* () {
|
|
1847
|
+
const absPrefix = /* @__PURE__ */ new Map();
|
|
1848
|
+
const iframeHostEncByChild = /* @__PURE__ */ new Map();
|
|
1849
|
+
absPrefix.set(context.rootId, "");
|
|
1850
|
+
const queue = [context.rootId];
|
|
1851
|
+
while (queue.length) {
|
|
1852
|
+
const parent = queue.shift();
|
|
1853
|
+
const parentAbs = absPrefix.get(parent);
|
|
1854
|
+
for (const child of context.frames) {
|
|
1855
|
+
if (context.parentByFrame.get(child) !== parent) continue;
|
|
1856
|
+
queue.push(child);
|
|
1857
|
+
const parentSess = parentSession(page, context.parentByFrame, child);
|
|
1858
|
+
const ownerBackendNodeId = yield (() => __async(null, null, function* () {
|
|
1859
|
+
try {
|
|
1860
|
+
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: child });
|
|
1861
|
+
return backendNodeId;
|
|
1862
|
+
} catch (e2) {
|
|
1863
|
+
return void 0;
|
|
1864
|
+
}
|
|
1865
|
+
}))();
|
|
1866
|
+
if (!ownerBackendNodeId) {
|
|
1867
|
+
absPrefix.set(child, parentAbs);
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
const parentDom = perFrameMaps.get(parent);
|
|
1871
|
+
const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;
|
|
1872
|
+
const iframeXPath = parentDom == null ? void 0 : parentDom.xpathMap[iframeEnc];
|
|
1873
|
+
const childAbs = iframeXPath ? prefixXPath(parentAbs || "/", iframeXPath) : parentAbs;
|
|
1874
|
+
absPrefix.set(child, childAbs);
|
|
1875
|
+
iframeHostEncByChild.set(child, iframeEnc);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
return { absPrefix, iframeHostEncByChild };
|
|
1879
|
+
});
|
|
1880
|
+
}
|
|
1881
|
+
function mergeFramesIntoSnapshot(context, perFrameMaps, perFrameOutlines, absPrefix, iframeHostEncByChild) {
|
|
1882
|
+
var _a4, _b, _c, _d2, _e;
|
|
1883
|
+
const combinedXpathMap = {};
|
|
1884
|
+
const combinedUrlMap = {};
|
|
1885
|
+
for (const frameId of context.frames) {
|
|
1886
|
+
const maps = perFrameMaps.get(frameId);
|
|
1887
|
+
if (!maps) continue;
|
|
1888
|
+
const abs = (_a4 = absPrefix.get(frameId)) != null ? _a4 : "";
|
|
1889
|
+
const isRoot = abs === "" || abs === "/";
|
|
1890
|
+
if (isRoot) {
|
|
1891
|
+
Object.assign(combinedXpathMap, maps.xpathMap);
|
|
1892
|
+
Object.assign(combinedUrlMap, maps.urlMap);
|
|
1893
|
+
continue;
|
|
1894
|
+
}
|
|
1895
|
+
for (const [encId, xp] of Object.entries(maps.xpathMap)) {
|
|
1896
|
+
combinedXpathMap[encId] = prefixXPath(abs, xp);
|
|
1897
|
+
}
|
|
1898
|
+
Object.assign(combinedUrlMap, maps.urlMap);
|
|
1899
|
+
}
|
|
1900
|
+
const idToTree = /* @__PURE__ */ new Map();
|
|
1901
|
+
for (const { frameId, outline } of perFrameOutlines) {
|
|
1902
|
+
const parentEnc = iframeHostEncByChild.get(frameId);
|
|
1903
|
+
if (parentEnc) idToTree.set(parentEnc, outline);
|
|
1904
|
+
}
|
|
1905
|
+
const rootOutline = (_e = (_d2 = (_b = perFrameOutlines.find((o) => o.frameId === context.rootId)) == null ? void 0 : _b.outline) != null ? _d2 : (_c = perFrameOutlines[0]) == null ? void 0 : _c.outline) != null ? _e : "";
|
|
1906
|
+
const combinedTree = injectSubtrees(rootOutline, idToTree);
|
|
1907
|
+
return {
|
|
1908
|
+
combinedTree,
|
|
1909
|
+
combinedXpathMap,
|
|
1910
|
+
combinedUrlMap,
|
|
1911
|
+
perFrame: perFrameOutlines.map(({ frameId, outline }) => {
|
|
1912
|
+
var _a5, _b2;
|
|
1913
|
+
const maps = perFrameMaps.get(frameId);
|
|
1914
|
+
return {
|
|
1915
|
+
frameId,
|
|
1916
|
+
outline,
|
|
1917
|
+
xpathMap: (_a5 = maps == null ? void 0 : maps.xpathMap) != null ? _a5 : {},
|
|
1918
|
+
urlMap: (_b2 = maps == null ? void 0 : maps.urlMap) != null ? _b2 : {}
|
|
1919
|
+
};
|
|
1920
|
+
})
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
var init_capture = __esm({
|
|
1924
|
+
"lib/v3/understudy/a11y/snapshot/capture.ts"() {
|
|
1925
|
+
init_logger();
|
|
1926
|
+
init_a11yTree();
|
|
1927
|
+
init_focusSelectors();
|
|
1928
|
+
init_domTree();
|
|
1929
|
+
init_treeFormatUtils();
|
|
1930
|
+
init_sessions();
|
|
1931
|
+
init_xpathUtils();
|
|
1932
|
+
}
|
|
1933
|
+
});
|
|
1934
|
+
|
|
1935
|
+
// lib/v3/understudy/a11yInvocation.ts
|
|
1936
|
+
function buildA11yInvocation(name, args) {
|
|
1937
|
+
const invocation = `${a11yScriptGlobalRefs[name]}(${args.join(", ")})`;
|
|
1938
|
+
return `(() => { ${a11yScriptBootstrap}; return ${invocation}; })()`;
|
|
1939
|
+
}
|
|
1940
|
+
var init_a11yInvocation = __esm({
|
|
1941
|
+
"lib/v3/understudy/a11yInvocation.ts"() {
|
|
1942
|
+
init_a11yScripts_generated();
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
|
|
1946
|
+
// lib/v3/understudy/a11y/snapshot/activeElement.ts
|
|
1947
|
+
function computeActiveElementXpath(page) {
|
|
1948
|
+
return __async(this, null, function* () {
|
|
1949
|
+
var _a4;
|
|
1950
|
+
const tree = page.getFullFrameTree();
|
|
1951
|
+
const parentByFrame = /* @__PURE__ */ new Map();
|
|
1952
|
+
(function index(n, parent) {
|
|
1953
|
+
var _a5;
|
|
1954
|
+
parentByFrame.set(n.frame.id, parent);
|
|
1955
|
+
for (const c of (_a5 = n.childFrames) != null ? _a5 : []) index(c, n.frame.id);
|
|
1956
|
+
})(tree, null);
|
|
1957
|
+
const frames = page.listAllFrameIds();
|
|
1958
|
+
let focusedFrameId = null;
|
|
1959
|
+
for (const fid of frames) {
|
|
1960
|
+
const sess = page.getSessionForFrame(fid);
|
|
1961
|
+
try {
|
|
1962
|
+
yield sess.send("Runtime.enable").catch(() => {
|
|
1963
|
+
});
|
|
1964
|
+
const ctxId = yield executionContexts.waitForMainWorld(sess, fid, 1e3).catch(() => {
|
|
1965
|
+
});
|
|
1966
|
+
const hasFocusExpr = buildA11yInvocation("documentHasFocusStrict", []);
|
|
1967
|
+
const evalParams = ctxId ? {
|
|
1968
|
+
contextId: ctxId,
|
|
1969
|
+
expression: hasFocusExpr,
|
|
1970
|
+
returnByValue: true
|
|
1971
|
+
} : { expression: hasFocusExpr, returnByValue: true };
|
|
1972
|
+
const { result } = yield sess.send(
|
|
1973
|
+
"Runtime.evaluate",
|
|
1974
|
+
evalParams
|
|
1975
|
+
);
|
|
1976
|
+
if ((result == null ? void 0 : result.value) === true) {
|
|
1977
|
+
focusedFrameId = fid;
|
|
1978
|
+
break;
|
|
1979
|
+
}
|
|
1980
|
+
} catch (e2) {
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
if (!focusedFrameId) focusedFrameId = page.mainFrameId();
|
|
1984
|
+
const focusedSession = page.getSessionForFrame(focusedFrameId);
|
|
1985
|
+
let objectId;
|
|
1986
|
+
try {
|
|
1987
|
+
yield focusedSession.send("Runtime.enable").catch(() => {
|
|
1988
|
+
});
|
|
1989
|
+
const ctxId = yield executionContexts.waitForMainWorld(focusedSession, focusedFrameId, 1e3).catch(() => {
|
|
1990
|
+
});
|
|
1991
|
+
const activeExpr = buildA11yInvocation("resolveDeepActiveElement", []);
|
|
1992
|
+
const evalParams = ctxId ? {
|
|
1993
|
+
contextId: ctxId,
|
|
1994
|
+
expression: activeExpr,
|
|
1995
|
+
returnByValue: false
|
|
1996
|
+
} : { expression: activeExpr, returnByValue: false };
|
|
1997
|
+
const { result } = yield focusedSession.send(
|
|
1998
|
+
"Runtime.evaluate",
|
|
1999
|
+
evalParams
|
|
2000
|
+
);
|
|
2001
|
+
objectId = result == null ? void 0 : result.objectId;
|
|
2002
|
+
} catch (e2) {
|
|
2003
|
+
objectId = void 0;
|
|
2004
|
+
}
|
|
2005
|
+
if (!objectId) return null;
|
|
2006
|
+
const leafXPath = yield (() => __async(null, null, function* () {
|
|
2007
|
+
try {
|
|
2008
|
+
const { result } = yield focusedSession.send("Runtime.callFunctionOn", {
|
|
2009
|
+
objectId,
|
|
2010
|
+
functionDeclaration: a11yScriptSources.nodeToAbsoluteXPath,
|
|
2011
|
+
returnByValue: true
|
|
2012
|
+
});
|
|
2013
|
+
try {
|
|
2014
|
+
yield focusedSession.send("Runtime.releaseObject", { objectId });
|
|
2015
|
+
} catch (e2) {
|
|
2016
|
+
}
|
|
2017
|
+
const xp = (result == null ? void 0 : result.value) || "";
|
|
2018
|
+
return typeof xp === "string" && xp ? xp : null;
|
|
2019
|
+
} catch (e2) {
|
|
2020
|
+
try {
|
|
2021
|
+
yield focusedSession.send("Runtime.releaseObject", { objectId });
|
|
2022
|
+
} catch (e3) {
|
|
2023
|
+
}
|
|
2024
|
+
return null;
|
|
2025
|
+
}
|
|
2026
|
+
}))();
|
|
2027
|
+
if (!leafXPath) return null;
|
|
2028
|
+
let prefix = "";
|
|
2029
|
+
let cur = focusedFrameId;
|
|
2030
|
+
while (cur) {
|
|
2031
|
+
const parent = (_a4 = parentByFrame.get(cur)) != null ? _a4 : null;
|
|
2032
|
+
if (!parent) break;
|
|
2033
|
+
const parentSess = page.getSessionForFrame(parent);
|
|
2034
|
+
try {
|
|
2035
|
+
const { backendNodeId } = yield parentSess.send("DOM.getFrameOwner", { frameId: cur });
|
|
2036
|
+
if (typeof backendNodeId === "number") {
|
|
2037
|
+
const xp = yield absoluteXPathForBackendNode(parentSess, backendNodeId);
|
|
2038
|
+
if (xp) prefix = prefix ? prefixXPath(prefix, xp) : normalizeXPath(xp);
|
|
2039
|
+
}
|
|
2040
|
+
} catch (e2) {
|
|
2041
|
+
}
|
|
2042
|
+
cur = parent;
|
|
2043
|
+
}
|
|
2044
|
+
return prefix ? prefixXPath(prefix, leafXPath) : normalizeXPath(leafXPath);
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
var init_activeElement = __esm({
|
|
2048
|
+
"lib/v3/understudy/a11y/snapshot/activeElement.ts"() {
|
|
2049
|
+
init_executionContextRegistry();
|
|
2050
|
+
init_a11yInvocation();
|
|
2051
|
+
init_a11yScripts_generated();
|
|
2052
|
+
init_xpathUtils();
|
|
2053
|
+
}
|
|
2054
|
+
});
|
|
2055
|
+
|
|
2056
|
+
// lib/v3/understudy/a11y/snapshot/coordinateResolver.ts
|
|
2057
|
+
function resolveXpathForLocation(page, x2, y) {
|
|
2058
|
+
return __async(this, null, function* () {
|
|
2059
|
+
var _a4, _b, _c, _d2, _e, _f, _g, _h;
|
|
2060
|
+
const tree = page.getFullFrameTree();
|
|
2061
|
+
const parentByFrame = /* @__PURE__ */ new Map();
|
|
2062
|
+
(function index(n, parent) {
|
|
2063
|
+
var _a5;
|
|
2064
|
+
parentByFrame.set(n.frame.id, parent);
|
|
2065
|
+
for (const c of (_a5 = n.childFrames) != null ? _a5 : []) index(c, n.frame.id);
|
|
2066
|
+
})(tree, null);
|
|
2067
|
+
const iframeChain = [];
|
|
2068
|
+
let curFrameId = page.mainFrameId();
|
|
2069
|
+
let curSession = page.getSessionForFrame(curFrameId);
|
|
2070
|
+
let curX = x2;
|
|
2071
|
+
let curY = y;
|
|
2072
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
2073
|
+
try {
|
|
2074
|
+
yield curSession.send("DOM.enable").catch(() => {
|
|
2075
|
+
});
|
|
2076
|
+
let sx = 0;
|
|
2077
|
+
let sy = 0;
|
|
2078
|
+
try {
|
|
2079
|
+
yield curSession.send("Runtime.enable").catch(() => {
|
|
2080
|
+
});
|
|
2081
|
+
const ctxId = yield executionContexts.waitForMainWorld(curSession, curFrameId).catch(() => {
|
|
2082
|
+
});
|
|
2083
|
+
const scrollExpr = buildA11yInvocation("getScrollOffsets", []);
|
|
2084
|
+
const evalParams = ctxId ? {
|
|
2085
|
+
contextId: ctxId,
|
|
2086
|
+
expression: scrollExpr,
|
|
2087
|
+
returnByValue: true
|
|
2088
|
+
} : { expression: scrollExpr, returnByValue: true };
|
|
2089
|
+
const { result } = yield curSession.send("Runtime.evaluate", evalParams);
|
|
2090
|
+
sx = Number((_b = (_a4 = result == null ? void 0 : result.value) == null ? void 0 : _a4.sx) != null ? _b : 0);
|
|
2091
|
+
sy = Number((_d2 = (_c = result == null ? void 0 : result.value) == null ? void 0 : _c.sy) != null ? _d2 : 0);
|
|
2092
|
+
} catch (e2) {
|
|
2093
|
+
}
|
|
2094
|
+
const xi = Math.max(0, Math.floor(curX + sx));
|
|
2095
|
+
const yi = Math.max(0, Math.floor(curY + sy));
|
|
2096
|
+
let res;
|
|
2097
|
+
try {
|
|
2098
|
+
res = yield curSession.send("DOM.getNodeForLocation", {
|
|
2099
|
+
x: xi,
|
|
2100
|
+
y: yi,
|
|
2101
|
+
includeUserAgentShadowDOM: false,
|
|
2102
|
+
ignorePointerEventsNone: false
|
|
2103
|
+
});
|
|
2104
|
+
} catch (e2) {
|
|
2105
|
+
return null;
|
|
2106
|
+
}
|
|
2107
|
+
const be = res == null ? void 0 : res.backendNodeId;
|
|
2108
|
+
const reportedFrameId = res == null ? void 0 : res.frameId;
|
|
2109
|
+
if (typeof be === "number" && reportedFrameId && reportedFrameId !== curFrameId) {
|
|
2110
|
+
const abs = yield buildAbsoluteXPathFromChain(
|
|
2111
|
+
iframeChain,
|
|
2112
|
+
curSession,
|
|
2113
|
+
be
|
|
2114
|
+
);
|
|
2115
|
+
return abs ? { frameId: reportedFrameId, backendNodeId: be, absoluteXPath: abs } : null;
|
|
2116
|
+
}
|
|
2117
|
+
if (typeof be !== "number") return null;
|
|
2118
|
+
let matchedChild;
|
|
2119
|
+
for (const fid of listChildrenOf(parentByFrame, curFrameId)) {
|
|
2120
|
+
try {
|
|
2121
|
+
const { backendNodeId } = yield curSession.send("DOM.getFrameOwner", { frameId: fid });
|
|
2122
|
+
if (backendNodeId === be) {
|
|
2123
|
+
matchedChild = fid;
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
} catch (e2) {
|
|
2127
|
+
continue;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
if (!matchedChild) {
|
|
2131
|
+
const abs = yield buildAbsoluteXPathFromChain(
|
|
2132
|
+
iframeChain,
|
|
2133
|
+
curSession,
|
|
2134
|
+
be
|
|
2135
|
+
);
|
|
2136
|
+
return abs ? { frameId: curFrameId, backendNodeId: be, absoluteXPath: abs } : null;
|
|
2137
|
+
}
|
|
2138
|
+
iframeChain.push({
|
|
2139
|
+
parentSession: curSession,
|
|
2140
|
+
iframeBackendNodeId: be
|
|
2141
|
+
});
|
|
2142
|
+
let left = 0;
|
|
2143
|
+
let top = 0;
|
|
2144
|
+
try {
|
|
2145
|
+
const { object } = yield curSession.send("DOM.resolveNode", { backendNodeId: be });
|
|
2146
|
+
const objectId = object == null ? void 0 : object.objectId;
|
|
2147
|
+
if (objectId) {
|
|
2148
|
+
const { result } = yield curSession.send("Runtime.callFunctionOn", {
|
|
2149
|
+
objectId,
|
|
2150
|
+
functionDeclaration: a11yScriptSources.getBoundingRectLite,
|
|
2151
|
+
returnByValue: true
|
|
2152
|
+
});
|
|
2153
|
+
left = Number((_f = (_e = result == null ? void 0 : result.value) == null ? void 0 : _e.left) != null ? _f : 0);
|
|
2154
|
+
top = Number((_h = (_g = result == null ? void 0 : result.value) == null ? void 0 : _g.top) != null ? _h : 0);
|
|
2155
|
+
yield curSession.send("Runtime.releaseObject", { objectId }).catch(() => {
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
} catch (e2) {
|
|
2159
|
+
}
|
|
2160
|
+
curX = Math.max(0, curX - left);
|
|
2161
|
+
curY = Math.max(0, curY - top);
|
|
2162
|
+
curFrameId = matchedChild;
|
|
2163
|
+
curSession = page.getSessionForFrame(curFrameId);
|
|
2164
|
+
} catch (e2) {
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
return null;
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
var init_coordinateResolver = __esm({
|
|
2172
|
+
"lib/v3/understudy/a11y/snapshot/coordinateResolver.ts"() {
|
|
2173
|
+
init_executionContextRegistry();
|
|
2174
|
+
init_a11yScripts_generated();
|
|
2175
|
+
init_a11yInvocation();
|
|
2176
|
+
init_focusSelectors();
|
|
2177
|
+
init_xpathUtils();
|
|
2178
|
+
}
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2181
|
+
// lib/v3/understudy/a11y/snapshot/index.ts
|
|
2182
|
+
var init_snapshot = __esm({
|
|
2183
|
+
"lib/v3/understudy/a11y/snapshot/index.ts"() {
|
|
2184
|
+
init_capture();
|
|
2185
|
+
init_activeElement();
|
|
2186
|
+
init_treeFormatUtils();
|
|
2187
|
+
init_coordinateResolver();
|
|
2050
2188
|
}
|
|
2051
2189
|
});
|
|
2052
2190
|
|