@browserbasehq/orca 3.2.1-preview.2 → 3.4.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/dist/cjs/lib/inference.js +2 -9
  2. package/dist/cjs/lib/inference.js.map +1 -1
  3. package/dist/cjs/lib/prompt.js +3 -1
  4. package/dist/cjs/lib/prompt.js.map +1 -1
  5. package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
  6. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  7. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
  8. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  9. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  10. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  11. package/dist/cjs/lib/v3/api.d.ts +1 -0
  12. package/dist/cjs/lib/v3/api.js +15 -3
  13. package/dist/cjs/lib/v3/api.js.map +1 -1
  14. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +1 -1
  15. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  16. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +1 -1
  17. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  18. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  19. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  20. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  21. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
  22. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  23. package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  24. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
  25. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  26. package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
  27. package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
  28. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
  29. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  30. package/dist/cjs/lib/v3/index.d.ts +1 -1
  31. package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
  32. package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
  33. package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
  34. package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
  35. package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
  36. package/dist/cjs/lib/v3/types/private/agent.js +11 -0
  37. package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
  38. package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
  39. package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
  40. package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
  41. package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
  42. package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
  43. package/dist/cjs/lib/v3/types/public/agent.js +3 -0
  44. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  45. package/dist/cjs/lib/v3/types/public/api.d.ts +5 -1
  46. package/dist/cjs/lib/v3/types/public/api.js +15 -2
  47. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  48. package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
  49. package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
  50. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  51. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  52. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  53. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
  54. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  55. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  56. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  57. package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
  58. package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
  59. package/dist/cjs/lib/v3/v3.d.ts +1 -0
  60. package/dist/cjs/lib/v3/v3.js +15 -14
  61. package/dist/cjs/lib/v3/v3.js.map +1 -1
  62. package/dist/cjs/lib/version.d.ts +1 -1
  63. package/dist/cjs/lib/version.js +1 -1
  64. package/dist/cjs/lib/version.js.map +1 -1
  65. package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
  66. package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
  67. package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
  68. package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
  69. package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
  70. package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
  71. package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
  72. package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
  73. package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
  74. package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
  75. package/dist/cjs/tests/unit/api-client-observe-variables.test.js +47 -0
  76. package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
  77. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
  78. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  79. package/dist/cjs/tests/unit/api-variables-schema.test.js +25 -0
  80. package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
  81. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  82. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
  83. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  84. package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
  85. package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
  86. package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
  87. package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  88. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
  89. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  90. package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
  91. package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
  92. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
  93. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  94. package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
  95. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  96. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  97. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  98. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  99. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  100. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  101. package/dist/esm/lib/inference.js +2 -9
  102. package/dist/esm/lib/inference.js.map +1 -1
  103. package/dist/esm/lib/prompt.js +3 -1
  104. package/dist/esm/lib/prompt.js.map +1 -1
  105. package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
  106. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  107. package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
  108. package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  109. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  110. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  111. package/dist/esm/lib/v3/api.d.ts +1 -0
  112. package/dist/esm/lib/v3/api.js +15 -3
  113. package/dist/esm/lib/v3/api.js.map +1 -1
  114. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +1 -1
  115. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  116. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +1 -1
  117. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  118. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  119. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  120. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  121. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
  122. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  123. package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  124. package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
  125. package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  126. package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
  127. package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
  128. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
  129. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  130. package/dist/esm/lib/v3/index.d.ts +1 -1
  131. package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
  132. package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
  133. package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
  134. package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
  135. package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
  136. package/dist/esm/lib/v3/types/private/agent.js +10 -1
  137. package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
  138. package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
  139. package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
  140. package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
  141. package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
  142. package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
  143. package/dist/esm/lib/v3/types/public/agent.js +3 -0
  144. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  145. package/dist/esm/lib/v3/types/public/api.d.ts +5 -1
  146. package/dist/esm/lib/v3/types/public/api.js +15 -2
  147. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  148. package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
  149. package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
  150. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  151. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  152. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  153. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
  154. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  155. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  156. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  157. package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
  158. package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
  159. package/dist/esm/lib/v3/v3.d.ts +1 -0
  160. package/dist/esm/lib/v3/v3.js +15 -14
  161. package/dist/esm/lib/v3/v3.js.map +1 -1
  162. package/dist/esm/lib/version.d.ts +1 -1
  163. package/dist/esm/lib/version.js +1 -1
  164. package/dist/esm/lib/version.js.map +1 -1
  165. package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
  166. package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
  167. package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
  168. package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
  169. package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
  170. package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
  171. package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
  172. package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
  173. package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
  174. package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
  175. package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
  176. package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
  177. package/dist/esm/tests/unit/api-client-observe-variables.test.js +47 -0
  178. package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
  179. package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
  180. package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  181. package/dist/esm/tests/unit/api-variables-schema.test.js +25 -0
  182. package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
  183. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  184. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
  185. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  186. package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
  187. package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
  188. package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
  189. package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  190. package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
  191. package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  192. package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
  193. package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
  194. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
  195. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  196. package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
  197. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  198. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  199. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  200. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  201. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  202. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  203. package/package.json +1 -1
  204. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
  205. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  206. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
  207. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  208. /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
  209. /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/capture.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAS9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAU,EACV,OAAyB;IAEzB,MAAM,MAAM,GAAG,OAAO,EAAE,YAAY,IAAI,IAAI,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;IAEzD,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAExC,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAC5C,IAAI,EACJ,OAAO,EACP,OAAO,EACP,MAAM,CACP,CAAC;IACF,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC9E,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,MAAM,mBAAmB,CAClE,IAAI,EACJ,OAAO,EACP,cAAc,EACd,OAAO,EACP,MAAM,EACN,aAAa,CACd,CAAC;IACF,MAAM,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,oBAAoB,CACpE,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,aAAa,CACd,CAAC;IAEF,OAAO,uBAAuB,CAC5B,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,oBAAoB,EACpB,aAAa,CACd,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAU;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,aAAa,GAAqB,IAAI,GAAG,EAAE,CAAC;IAClD,CAAC,SAAS,KAAK,CAAC,CAA0B,EAAE,MAAqB;QAC/D,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE;YAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAU,EACV,OAAoC,EACpC,OAAqB,EACrB,MAAe;IAEf,MAAM,cAAc,GAAG,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IAEjC,MAAM,gBAAgB,GAAG,GAAG,EAAE;QAC5B,QAAQ,CAAC;YACP,OAAO,EAAE,sEAAsE;YAC/E,KAAK,EAAE,CAAC;YACR,SAAS,EAAE;gBACT,SAAS,EAAE;oBACT,KAAK,EAAE,aAAa,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE;oBACpD,IAAI,EAAE,QAAQ;iBACf;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,aAAqB,CAAC;QAC1B,IAAI,YAAgC,CAAC;QACrC,IAAI,SAA6B,CAAC;QAElC,MAAM,cAAc,GAClB,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACpE,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,MAAM,wBAAwB,CACxC,IAAI,EACJ,KAAK,EACL,OAAO,CAAC,aAAa,EACrB,OAAO,CAAC,MAAM,CACf,CAAC;YACF,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;YAClC,YAAY,GAAG,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC;YAC1C,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAC9C,IAAI,EACJ,cAAc,EACd,OAAO,CAAC,aAAa,EACrB,OAAO,CAAC,MAAM,CACf,CAAC;YACF,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;YACrC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC;YAChD,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAC/B,CAAC;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1D,MAAM,mBAAmB,GACvB,CAAC,CAAC,QAAQ;YACV,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACrE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,iBAAiB,CACrE,UAAU,EACV,aAAa,EACb,MAAM,EACN,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAC5C,mBAAmB,CACpB,CAAC;QAEF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,YAAY,CAC1D,UAAU,EACV,aAAa,EACb;YACE,aAAa,EAAE,YAAY,IAAI,SAAS;YACxC,UAAU;YACV,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,KAAK;YAC5C,aAAa;YACb,MAAM,EAAE,CAAC,aAAa,EAAE,EAAE,CACxB,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,aAAa,EAAE;SACvD,CACF,CAAC;QAEF,MAAM,cAAc,GAA2B,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,SAAS,IAAI,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,2EAA2E;YAC3E,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnD,cAAc,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAA2B,EAAE,GAAG,MAAM,EAAE,CAAC;QAE3D,MAAM,QAAQ,GAAmB;YAC/B,YAAY,EAAE,OAAO;YACrB,gBAAgB,EAAE,cAAc;YAChC,cAAc,EAAE,YAAY;YAC5B,QAAQ,EAAE;gBACR;oBACE,OAAO,EAAE,aAAa;oBACtB,OAAO;oBACP,QAAQ;oBACR,MAAM;iBACP;aACF;SACF,CAAC;QAEF,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,gBAAgB,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB,EAAE,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAU,EACV,MAAgB,EAChB,MAAe;IAEf,MAAM,cAAc,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC1D,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;IACtD,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,MAAM,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrD,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAU,EACV,OAAqB,EACrB,cAA4C,EAC5C,OAAoC,EACpC,MAAe,EACf,QAAkB;IAKlB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;IACrD,MAAM,gBAAgB,GAAgD,EAAE,CAAC;IAEzE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,MAAM,CAAC;QAC9B,IAAI,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC/C,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,mBAAmB,GACvB,CAAC,CAAC,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;QACtD,IAAI,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC;QAChC,IAAI,mBAAmB,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CACvC,mBAAmB,EACnB,EAAE,OAAO,EAAE,CACZ,CAAC;gBACF,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAC3D,IAAI,OAAO,IAAI,KAAK,QAAQ;wBAAE,SAAS,GAAG,IAAI,CAAC;gBACjD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,EAAE;YACJ,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAC5C,MAAM,aAAa,GAA4B,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAChE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;QAElD,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,WAAW,KAAK,SAAS;gBAAE,SAAS;YAExC,wEAAwE;YACxE,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;YACpB,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;YACpB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,GAAG;gBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;YAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACxD,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE;YAC5D,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,KAAK;YAC5C,UAAU;YACV,aAAa;YACb,MAAM,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,aAAa,EAAE;SAC1E,CAAC,CAAC;QAEH,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAU,EACV,OAAqB,EACrB,YAAuC,EACvC,QAAkB;IAKlB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvD,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QAC9B,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;QAEzC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS;YACnC,IAAI,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,MAAM;gBAAE,SAAS;YAC1D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAElB,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAErE,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE;gBAC3C,IAAI,CAAC;oBACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,UAAU,CAAC,IAAI,CAE5C,mBAAmB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC5C,OAAO,aAAa,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;YAEL,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACxB,qEAAqE;gBACrE,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAChC,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,kBAAkB,EAAE,CAAC;YACrE,MAAM,WAAW,GAAG,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;YAEnD,MAAM,QAAQ,GAAG,WAAW;gBAC1B,CAAC,CAAC,WAAW,CAAC,SAAS,IAAI,GAAG,EAAE,WAAW,CAAC;gBAC5C,CAAC,CAAC,SAAS,CAAC;YAEd,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC/B,oBAAoB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAqB,EACrB,YAAuC,EACvC,gBAA6D,EAC7D,SAA8B,EAC9B,oBAAyC,EACzC,QAAkB;IAElB,MAAM,gBAAgB,GAA2B,EAAE,CAAC;IACpD,MAAM,cAAc,GAA2B,EAAE,CAAC;IAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,CAAC;QAEzC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxD,gBAAgB,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpD,8EAA8E;QAC9E,IAAI,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,WAAW,GACf,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;QACnE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO;QAC5B,EAAE,CAAC;IACL,MAAM,YAAY,GAAG,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE3D,OAAO;QACL,YAAY;QACZ,gBAAgB;QAChB,cAAc;QACd,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO;gBACL,OAAO;gBACP,OAAO;gBACP,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE;gBAC9B,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE;aAC3B,CAAC;QACJ,CAAC,CAAC;KACH,CAAC;AACJ,CAAC","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { Page } from \"../../page.js\";\nimport { v3Logger } from \"../../../logger.js\";\nimport type {\n FrameContext,\n FrameDomMaps,\n FrameParentIndex,\n HybridSnapshot,\n SnapshotOptions,\n SessionDomIndex,\n} from \"../../../types/private/index.js\";\nimport { a11yForFrame } from \"./a11yTree.js\";\nimport {\n resolveCssFocusFrameAndTail,\n resolveFocusFrameAndTail,\n} from \"./focusSelectors.js\";\nimport {\n buildSessionDomIndex,\n domMapsForSession,\n relativizeXPath,\n} from \"./domTree.js\";\nimport { injectSubtrees } from \"./treeFormatUtils.js\";\nimport { ownerSession, parentSession } from \"./sessions.js\";\nimport { normalizeXPath, prefixXPath } from \"./xpathUtils.js\";\n\n/**\n * Capture a hybrid DOM + Accessibility snapshot for the provided page.\n *\n * Flow overview:\n * 1. (Optional) Scope directly to a requested selector. We walk iframe hops to\n * find the owning frame, build just that frame’s DOM + AX tree, and bail out\n * early when the subtree satisfies the caller.\n * 2. Build DOM indexes for every unique CDP session. DOM.getDocument is called\n * once per session and hydrated so per-frame slices can share the result.\n * 3. Slice each frame’s DOM data from its session index and fetch its AX tree.\n * This yields relative XPath/tag/url maps for the document rooted at that frame.\n * 4. Walk the frame tree to compute absolute iframe prefixes. Every child frame\n * needs the XPath of the iframe element that hosts it so we can prefix maps.\n * 5. Merge all per-frame results into global combined maps and stitch the text\n * outline. The final payload mirrors the legacy shape but is built in layers.\n *\n * Each numbered block below references the step above for easier debugging.\n */\nexport async function captureHybridSnapshot(\n page: Page,\n options?: SnapshotOptions,\n): Promise<HybridSnapshot> {\n const pierce = options?.pierceShadow ?? true;\n const includeIframes = options?.includeIframes !== false;\n\n const context = buildFrameContext(page);\n\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n );\n if (scopedSnapshot) return scopedSnapshot;\n\n const framesInScope = includeIframes ? [...context.frames] : [context.rootId];\n if (!framesInScope.includes(context.rootId)) {\n framesInScope.unshift(context.rootId);\n }\n\n const sessionToIndex = await buildSessionIndexes(page, framesInScope, pierce);\n const { perFrameMaps, perFrameOutlines } = await collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n options,\n pierce,\n framesInScope,\n );\n const { absPrefix, iframeHostEncByChild } = await computeFramePrefixes(\n page,\n context,\n perFrameMaps,\n framesInScope,\n );\n\n return mergeFramesIntoSnapshot(\n context,\n perFrameMaps,\n perFrameOutlines,\n absPrefix,\n iframeHostEncByChild,\n framesInScope,\n );\n}\n\n/**\n * Snapshot the current frame tree so downstream helpers have consistent topology\n * without re-querying CDP. The map is intentionally shallow (frameId → parentId)\n * so it is serializable/testable without holding on to CDP handles.\n */\nexport function buildFrameContext(page: Page): FrameContext {\n const rootId = page.mainFrameId();\n const frameTree = page.asProtocolFrameTree(rootId);\n const parentByFrame: FrameParentIndex = new Map();\n (function index(n: Protocol.Page.FrameTree, parent: string | null) {\n parentByFrame.set(n.frame.id, parent);\n for (const c of n.childFrames ?? []) index(c, n.frame.id);\n })(frameTree, null);\n const frames = page.listAllFrameIds();\n return { rootId, parentByFrame, frames };\n}\n\n/**\n * Step 1 – scoped snapshot fast-path. If a selector is provided we try to:\n * 1) Resolve the selector (XPath or CSS) across iframes.\n * 2) Build DOM + AX data only for the owning frame.\n * 3) Bail out early when the selector's subtree satisfies the request.\n *\n * Returns `null` when scoping fails (e.g., selector miss) so the caller can\n * fall back to the full multi-frame snapshot.\n */\nexport async function tryScopedSnapshot(\n page: Page,\n options: SnapshotOptions | undefined,\n context: FrameContext,\n pierce: boolean,\n): Promise<HybridSnapshot | null> {\n const requestedFocus = options?.focusSelector?.trim();\n if (!requestedFocus) return null;\n\n const logScopeFallback = () => {\n v3Logger({\n message: `Unable to narrow scope with selector. Falling back to using full DOM`,\n level: 1,\n auxiliary: {\n arguments: {\n value: `selector: ${options?.focusSelector?.trim()}`,\n type: \"string\",\n },\n },\n });\n };\n\n try {\n let targetFrameId: string;\n let tailSelector: string | undefined;\n let absPrefix: string | undefined;\n\n const looksLikeXPath =\n /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith(\"/\");\n if (looksLikeXPath) {\n const focus = normalizeXPath(requestedFocus);\n const hit = await resolveFocusFrameAndTail(\n page,\n focus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = hit.targetFrameId;\n tailSelector = hit.tailXPath || undefined;\n absPrefix = hit.absPrefix;\n } else {\n const cssHit = await resolveCssFocusFrameAndTail(\n page,\n requestedFocus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = cssHit.targetFrameId;\n tailSelector = cssHit.tailSelector || undefined;\n absPrefix = cssHit.absPrefix;\n }\n\n const owningSess = ownerSession(page, targetFrameId);\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const { tagNameMap, xpathMap, scrollableMap } = await domMapsForSession(\n owningSess,\n targetFrameId,\n pierce,\n (fid, be) => `${page.getOrdinal(fid)}-${be}`,\n sameSessionAsParent,\n );\n\n const { outline, urlMap, scopeApplied } = await a11yForFrame(\n owningSess,\n targetFrameId,\n {\n focusSelector: tailSelector || undefined,\n tagNameMap,\n experimental: options?.experimental ?? false,\n scrollableMap,\n encode: (backendNodeId) =>\n `${page.getOrdinal(targetFrameId)}-${backendNodeId}`,\n },\n );\n\n const scopedXpathMap: Record<string, string> = {};\n const abs = absPrefix ?? \"\";\n const isRoot = !abs || abs === \"/\";\n if (isRoot) {\n Object.assign(scopedXpathMap, xpathMap);\n } else {\n // Prefix relative XPaths so the scoped result matches the global encoding.\n for (const [encId, xp] of Object.entries(xpathMap)) {\n scopedXpathMap[encId] = prefixXPath(abs, xp);\n }\n }\n\n const scopedUrlMap: Record<string, string> = { ...urlMap };\n\n const snapshot: HybridSnapshot = {\n combinedTree: outline,\n combinedXpathMap: scopedXpathMap,\n combinedUrlMap: scopedUrlMap,\n perFrame: [\n {\n frameId: targetFrameId,\n outline,\n xpathMap,\n urlMap,\n },\n ],\n };\n\n if (scopeApplied) {\n return snapshot;\n }\n\n logScopeFallback();\n } catch {\n logScopeFallback();\n }\n return null;\n}\n\n/**\n * Step 2 – call DOM.getDocument once per unique CDP session and hydrate the\n * result so per-frame slices can share the structure. We key by session id\n * because same process iframes live inside the same session.\n */\nexport async function buildSessionIndexes(\n page: Page,\n frames: string[],\n pierce: boolean,\n): Promise<Map<string, SessionDomIndex>> {\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const sessionById = new Map<string, CDPSessionLike>();\n for (const frameId of frames) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n if (!sessionById.has(sid)) sessionById.set(sid, sess);\n }\n for (const [sid, sess] of sessionById.entries()) {\n const idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n return sessionToIndex;\n}\n\n/**\n * Step 3 – derive per-frame DOM maps and accessibility outlines.\n * Each frame:\n * - slices the shared session index down to its document root\n * - builds frame-aware encoded ids (ordinal-backendNodeId)\n * - collects tag/xpath/scrollability maps for DOM-based lookups\n * - fetches its AX tree to produce outlines and URL maps\n */\nexport async function collectPerFrameMaps(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n options: SnapshotOptions | undefined,\n pierce: boolean,\n frameIds: string[],\n): Promise<{\n perFrameMaps: Map<string, FrameDomMaps>;\n perFrameOutlines: Array<{ frameId: string; outline: string }>;\n}> {\n const perFrameMaps = new Map<string, FrameDomMaps>();\n const perFrameOutlines: Array<{ frameId: string; outline: string }> = [];\n\n for (const frameId of frameIds) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n let idx = sessionToIndex.get(sid);\n if (!idx) {\n idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId && ownerSession(page, parentId) === sess;\n let docRootBe = idx.rootBackend;\n if (sameSessionAsParent) {\n try {\n const { backendNodeId } = await sess.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId === \"number\") {\n const cdBe = idx.contentDocRootByIframe.get(backendNodeId);\n if (typeof cdBe === \"number\") docRootBe = cdBe;\n }\n } catch {\n //\n }\n }\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n const enc = (be: number) => `${page.getOrdinal(frameId)}-${be}`;\n const baseAbs = idx.absByBe.get(docRootBe) ?? \"/\";\n\n for (const [be, nodeAbs] of idx.absByBe.entries()) {\n const nodeDocRoot = idx.docRootOf.get(be);\n if (nodeDocRoot !== docRootBe) continue;\n\n // Translate absolute XPaths into document-relative ones for this frame.\n const rel = relativizeXPath(baseAbs, nodeAbs);\n const key = enc(be);\n xpathMap[key] = rel;\n const tag = idx.tagByBe.get(be);\n if (tag) tagNameMap[key] = tag;\n if (idx.scrollByBe.get(be)) scrollableMap[key] = true;\n }\n\n const { outline, urlMap } = await a11yForFrame(sess, frameId, {\n experimental: options?.experimental ?? false,\n tagNameMap,\n scrollableMap,\n encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`,\n });\n\n perFrameOutlines.push({ frameId, outline });\n perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });\n }\n\n return { perFrameMaps, perFrameOutlines };\n}\n\n/**\n * Step 4 – walk the frame tree (parent-first) to compute absolute prefixes for\n * every frame. The prefix is the absolute XPath of the iframe element hosting\n * the frame, so we can later convert relative XPaths into cross-frame ones.\n */\nexport async function computeFramePrefixes(\n page: Page,\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n frameIds: string[],\n): Promise<{\n absPrefix: Map<string, string>;\n iframeHostEncByChild: Map<string, string>;\n}> {\n const absPrefix = new Map<string, string>();\n const iframeHostEncByChild = new Map<string, string>();\n absPrefix.set(context.rootId, \"\");\n const included = new Set(frameIds);\n\n const queue: string[] = [];\n if (included.has(context.rootId)) {\n queue.push(context.rootId);\n }\n\n while (queue.length) {\n const parent = queue.shift()!;\n const parentAbs = absPrefix.get(parent)!;\n\n for (const child of context.frames) {\n if (!included.has(child)) continue;\n if (context.parentByFrame.get(child) !== parent) continue;\n queue.push(child);\n\n const parentSess = parentSession(page, context.parentByFrame, child);\n\n const ownerBackendNodeId = await (async () => {\n try {\n const { backendNodeId } = await parentSess.send<{\n backendNodeId?: number;\n }>(\"DOM.getFrameOwner\", { frameId: child });\n return backendNodeId;\n } catch {\n return undefined;\n }\n })();\n\n if (!ownerBackendNodeId) {\n // OOPIFs resolved via a different session inherit the parent prefix.\n absPrefix.set(child, parentAbs);\n continue;\n }\n\n const parentDom = perFrameMaps.get(parent);\n const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;\n const iframeXPath = parentDom?.xpathMap[iframeEnc];\n\n const childAbs = iframeXPath\n ? prefixXPath(parentAbs || \"/\", iframeXPath)\n : parentAbs;\n\n absPrefix.set(child, childAbs);\n iframeHostEncByChild.set(child, iframeEnc);\n }\n }\n\n return { absPrefix, iframeHostEncByChild };\n}\n\n/**\n * Step 5 – merge per-frame maps into the combined snapshot payload. We prefix\n * each frame's relative XPaths with the absolute path collected in step 4,\n * merge URL maps, and stitch text outlines by nesting child trees under the\n * encoded id of their parent iframe host.\n */\nexport function mergeFramesIntoSnapshot(\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n perFrameOutlines: Array<{ frameId: string; outline: string }>,\n absPrefix: Map<string, string>,\n iframeHostEncByChild: Map<string, string>,\n frameIds: string[],\n): HybridSnapshot {\n const combinedXpathMap: Record<string, string> = {};\n const combinedUrlMap: Record<string, string> = {};\n\n for (const frameId of frameIds) {\n const maps = perFrameMaps.get(frameId);\n if (!maps) continue;\n\n const abs = absPrefix.get(frameId) ?? \"\";\n const isRoot = abs === \"\" || abs === \"/\";\n\n if (isRoot) {\n Object.assign(combinedXpathMap, maps.xpathMap);\n Object.assign(combinedUrlMap, maps.urlMap);\n continue;\n }\n\n for (const [encId, xp] of Object.entries(maps.xpathMap)) {\n combinedXpathMap[encId] = prefixXPath(abs, xp);\n }\n Object.assign(combinedUrlMap, maps.urlMap);\n }\n\n const idToTree = new Map<string, string>();\n for (const { frameId, outline } of perFrameOutlines) {\n const parentEnc = iframeHostEncByChild.get(frameId);\n // The key is the parent iframe's encoded id so injectSubtrees can nest lines.\n if (parentEnc) idToTree.set(parentEnc, outline);\n }\n\n const rootOutline =\n perFrameOutlines.find((o) => o.frameId === context.rootId)?.outline ??\n perFrameOutlines[0]?.outline ??\n \"\";\n const combinedTree = injectSubtrees(rootOutline, idToTree);\n\n return {\n combinedTree,\n combinedXpathMap,\n combinedUrlMap,\n perFrame: perFrameOutlines.map(({ frameId, outline }) => {\n const maps = perFrameMaps.get(frameId);\n return {\n frameId,\n outline,\n xpathMap: maps?.xpathMap ?? {},\n urlMap: maps?.urlMap ?? {},\n };\n }),\n };\n}\n"]}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/capture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { Page } from \"../../page.js\";\nimport { Frame } from \"../../frame.js\";\nimport {\n FrameSelectorResolver,\n type ResolvedNode,\n type SelectorQuery,\n} from \"../../selectorResolver.js\";\nimport { v3Logger } from \"../../../logger.js\";\nimport type {\n FrameContext,\n FrameDomMaps,\n FrameParentIndex,\n HybridSnapshot,\n SnapshotOptions,\n SessionDomIndex,\n} from \"../../../types/private/index.js\";\nimport { a11yForFrame } from \"./a11yTree.js\";\nimport {\n resolveCssFocusFrameAndTail,\n resolveFocusFrameAndTail,\n listChildrenOf,\n} from \"./focusSelectors.js\";\nimport {\n buildSessionDomIndex,\n domMapsForSession,\n relativizeXPath,\n} from \"./domTree.js\";\nimport { injectSubtrees } from \"./treeFormatUtils.js\";\nimport { ownerSession, parentSession } from \"./sessions.js\";\nimport { normalizeXPath, prefixXPath } from \"./xpathUtils.js\";\n\ntype IgnoredNodeMap = Map<string, Set<number>>;\ntype Interval = { start: number; end: number };\ntype ExclusionIntervalsByFrame = Map<string, Interval[]>;\ntype ChildFrameHost = { childFrameId: string; hostBackendNodeId: number };\ntype ChildFramesByParent = Map<string, ChildFrameHost[]>;\n\n/**\n * Capture a hybrid DOM + Accessibility snapshot for the provided page.\n *\n * Flow overview:\n * 1. (Optional) Scope directly to a requested selector. We walk iframe hops to\n * find the owning frame, build just that frame’s DOM + AX tree, and bail out\n * early when the subtree satisfies the caller.\n * 2. Build DOM indexes for every unique CDP session. DOM.getDocument is called\n * once per session and hydrated so per-frame slices can share the result.\n * 3. Slice each frame’s DOM data from its session index and fetch its AX tree.\n * This yields relative XPath/tag/url maps for the document rooted at that frame.\n * 4. Walk the frame tree to compute absolute iframe prefixes. Every child frame\n * needs the XPath of the iframe element that hosts it so we can prefix maps.\n * 5. Merge all per-frame results into global combined maps and stitch the text\n * outline. The final payload mirrors the legacy shape but is built in layers.\n *\n * Each numbered block below references the step above for easier debugging.\n */\nexport async function captureHybridSnapshot(\n page: Page,\n options?: SnapshotOptions,\n): Promise<HybridSnapshot> {\n const pierce = options?.pierceShadow ?? true;\n const includeIframes = options?.includeIframes !== false;\n const hasIgnoreSelectors = (options?.ignoreSelectors?.length ?? 0) > 0;\n\n const context = buildFrameContext(page);\n const framesInScope = includeIframes ? [...context.frames] : [context.rootId];\n if (!framesInScope.includes(context.rootId)) {\n framesInScope.unshift(context.rootId);\n }\n\n if (!hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n new Map<string, SessionDomIndex>(),\n new Map(),\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const sessionToIndex = await buildSessionIndexes(page, framesInScope, pierce);\n const ignoredNodesByFrame = await resolveIgnoredNodes(\n page,\n options?.ignoreSelectors,\n context,\n sessionToIndex,\n );\n const exclusionIntervalsByFrame = await buildFrameExclusionIntervals(\n page,\n context,\n sessionToIndex,\n ignoredNodesByFrame,\n );\n if (hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n sessionToIndex,\n exclusionIntervalsByFrame,\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const { perFrameMaps, perFrameOutlines } = await collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n options,\n pierce,\n framesInScope,\n exclusionIntervalsByFrame,\n );\n const { absPrefix, iframeHostEncByChild } = await computeFramePrefixes(\n page,\n context,\n perFrameMaps,\n framesInScope,\n );\n\n return mergeFramesIntoSnapshot(\n context,\n perFrameMaps,\n perFrameOutlines,\n absPrefix,\n iframeHostEncByChild,\n framesInScope,\n );\n}\n\n/**\n * Snapshot the current frame tree so downstream helpers have consistent topology\n * without re-querying CDP. The map is intentionally shallow (frameId → parentId)\n * so it is serializable/testable without holding on to CDP handles.\n */\nexport function buildFrameContext(page: Page): FrameContext {\n const rootId = page.mainFrameId();\n const frameTree = page.asProtocolFrameTree(rootId);\n const parentByFrame: FrameParentIndex = new Map();\n (function index(n: Protocol.Page.FrameTree, parent: string | null) {\n parentByFrame.set(n.frame.id, parent);\n for (const c of n.childFrames ?? []) index(c, n.frame.id);\n })(frameTree, null);\n const frames = page.listAllFrameIds();\n return { rootId, parentByFrame, frames };\n}\n\n/**\n * Step 1 – scoped snapshot fast-path. If a selector is provided we try to:\n * 1) Resolve the selector (XPath or CSS) across iframes.\n * 2) Build DOM + AX data only for the owning frame.\n * 3) Bail out early when the selector's subtree satisfies the request.\n *\n * Returns `null` when scoping fails (e.g., selector miss) so the caller can\n * fall back to the full multi-frame snapshot.\n */\nexport async function tryScopedSnapshot(\n page: Page,\n options: SnapshotOptions | undefined,\n context: FrameContext,\n pierce: boolean,\n sessionToIndex: Map<string, SessionDomIndex>,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<HybridSnapshot | null> {\n const requestedFocus = options?.focusSelector?.trim();\n if (!requestedFocus) return null;\n\n const logScopeFallback = () => {\n v3Logger({\n message: `Unable to narrow scope with selector. Falling back to using full DOM`,\n level: 1,\n auxiliary: {\n arguments: {\n value: `selector: ${options?.focusSelector?.trim()}`,\n type: \"string\",\n },\n },\n });\n };\n\n try {\n let targetFrameId: string;\n let tailSelector: string | undefined;\n let absPrefix: string | undefined;\n\n const looksLikeXPath =\n /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith(\"/\");\n if (looksLikeXPath) {\n const focus = normalizeXPath(requestedFocus);\n const hit = await resolveFocusFrameAndTail(\n page,\n focus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = hit.targetFrameId;\n tailSelector = hit.tailXPath || undefined;\n absPrefix = hit.absPrefix;\n } else {\n const cssHit = await resolveCssFocusFrameAndTail(\n page,\n requestedFocus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = cssHit.targetFrameId;\n tailSelector = cssHit.tailSelector || undefined;\n absPrefix = cssHit.absPrefix;\n }\n\n const owningSess = ownerSession(page, targetFrameId);\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const { tagNameMap, xpathMap, scrollableMap } = await domMapsForSession(\n owningSess,\n targetFrameId,\n pierce,\n (fid, be) => `${page.getOrdinal(fid)}-${be}`,\n sameSessionAsParent,\n );\n\n const { outline, urlMap, scopeApplied } = await a11yForFrame(\n owningSess,\n targetFrameId,\n {\n focusSelector: tailSelector || undefined,\n isIgnoredBackendNode: makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n ),\n tagNameMap,\n experimental: options?.experimental ?? false,\n scrollableMap,\n encode: (backendNodeId) =>\n `${page.getOrdinal(targetFrameId)}-${backendNodeId}`,\n },\n );\n\n const scopedXpathMap: Record<string, string> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n );\n const abs = absPrefix ?? \"\";\n const isRoot = !abs || abs === \"/\";\n if (isRoot) {\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = xp;\n }\n } else {\n // Prefix relative XPaths so the scoped result matches the global encoding.\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = prefixXPath(abs, xp);\n }\n }\n\n const scopedUrlMap: Record<string, string> = { ...urlMap };\n\n const snapshot: HybridSnapshot = {\n combinedTree: outline,\n combinedXpathMap: scopedXpathMap,\n combinedUrlMap: scopedUrlMap,\n perFrame: [\n {\n frameId: targetFrameId,\n outline,\n xpathMap,\n urlMap,\n },\n ],\n };\n\n if (scopeApplied) {\n return snapshot;\n }\n\n logScopeFallback();\n } catch {\n logScopeFallback();\n }\n return null;\n}\n\n/**\n * Step 2 – call DOM.getDocument once per unique CDP session and hydrate the\n * result so per-frame slices can share the structure. We key by session id\n * because same process iframes live inside the same session.\n */\nexport async function buildSessionIndexes(\n page: Page,\n frames: string[],\n pierce: boolean,\n): Promise<Map<string, SessionDomIndex>> {\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const sessionById = new Map<string, CDPSessionLike>();\n for (const frameId of frames) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n if (!sessionById.has(sid)) sessionById.set(sid, sess);\n }\n for (const [sid, sess] of sessionById.entries()) {\n const idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n return sessionToIndex;\n}\n\n/**\n * Step 3 – derive per-frame DOM maps and accessibility outlines.\n * Each frame:\n * - slices the shared session index down to its document root\n * - builds frame-aware encoded ids (ordinal-backendNodeId)\n * - collects tag/xpath/scrollability maps for DOM-based lookups\n * - fetches its AX tree to produce outlines and URL maps\n */\nexport async function collectPerFrameMaps(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n options: SnapshotOptions | undefined,\n pierce: boolean,\n frameIds: string[],\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<{\n perFrameMaps: Map<string, FrameDomMaps>;\n perFrameOutlines: Array<{ frameId: string; outline: string }>;\n}> {\n const perFrameMaps = new Map<string, FrameDomMaps>();\n const perFrameOutlines: Array<{ frameId: string; outline: string }> = [];\n\n for (const frameId of frameIds) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n let idx = sessionToIndex.get(sid);\n if (!idx) {\n idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId && ownerSession(page, parentId) === sess;\n\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n frameId,\n idx,\n exclusionIntervalsByFrame,\n );\n const enc = (be: number) => `${page.getOrdinal(frameId)}-${be}`;\n const baseAbs = idx.absByBe.get(docRootBe) ?? \"/\";\n\n for (const [be, nodeAbs] of idx.absByBe.entries()) {\n const nodeDocRoot = idx.docRootOf.get(be);\n if (nodeDocRoot !== docRootBe) continue;\n if (isIgnoredBackendNode?.(be)) continue;\n\n // Translate absolute XPaths into document-relative ones for this frame.\n const rel = relativizeXPath(baseAbs, nodeAbs);\n const key = enc(be);\n xpathMap[key] = rel;\n const tag = idx.tagByBe.get(be);\n if (tag) tagNameMap[key] = tag;\n if (idx.scrollByBe.get(be)) scrollableMap[key] = true;\n }\n\n const { outline, urlMap } = await a11yForFrame(sess, frameId, {\n isIgnoredBackendNode,\n experimental: options?.experimental ?? false,\n tagNameMap,\n scrollableMap,\n encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`,\n });\n\n perFrameOutlines.push({ frameId, outline });\n perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });\n }\n\n return { perFrameMaps, perFrameOutlines };\n}\n\nexport async function resolveIgnoredNodes(\n page: Page,\n ignoreSelectors: string[] | undefined,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<IgnoredNodeMap> {\n const ignoredNodesByFrame: IgnoredNodeMap = new Map();\n\n for (const rawSelector of ignoreSelectors ?? []) {\n const selector = rawSelector.trim();\n if (!selector) continue;\n\n try {\n const resolved = await resolveIgnoredNodesForSelector(\n page,\n selector,\n context,\n sessionToIndex,\n );\n for (const match of resolved) {\n const nodes =\n ignoredNodesByFrame.get(match.frameId) ?? new Set<number>();\n nodes.add(match.backendNodeId);\n ignoredNodesByFrame.set(match.frameId, nodes);\n }\n } catch {\n continue;\n }\n }\n\n return ignoredNodesByFrame;\n}\n\nasync function resolveIgnoredNodesForSelector(\n page: Page,\n selector: string,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const looksLikeXPath = /^xpath=/i.test(selector) || selector.startsWith(\"/\");\n\n if (looksLikeXPath) {\n const hit = await resolveFocusFrameAndTail(\n page,\n normalizeXPath(selector),\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n const tailXPath = hit.tailXPath || \"/\";\n if (tailXPath === \"/\") {\n const idx = ownerSessionIndexForFrame(\n page,\n targetFrameId,\n sessionToIndex,\n );\n if (!idx) return [];\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const backendNodeId = await resolveFrameDocRootBackendId(\n page,\n targetFrameId,\n idx,\n sameSessionAsParent,\n );\n return [{ frameId: targetFrameId, backendNodeId }];\n }\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"xpath\",\n value: tailXPath,\n });\n }\n\n const hit = await resolveCssFocusFrameAndTail(\n page,\n selector,\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"css\",\n value: hit.tailSelector || selector,\n });\n}\n\nasync function resolveIgnoredNodesInFrame(\n page: Page,\n frameId: string,\n query: SelectorQuery,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const session = ownerSession(page, frameId);\n const frame = new Frame(session, frameId, \"\", false);\n const resolver = new FrameSelectorResolver(frame);\n const resolvedNodes = await resolver.resolveAll(query);\n if (!resolvedNodes.length) return [];\n\n const backendNodeIds = await describeResolvedNodes(session, resolvedNodes);\n return backendNodeIds.map((backendNodeId) => ({ frameId, backendNodeId }));\n}\n\nasync function describeResolvedNodes(\n session: CDPSessionLike,\n resolvedNodes: ResolvedNode[],\n): Promise<number[]> {\n const backendNodeIds = new Set<number>();\n\n try {\n for (const resolvedNode of resolvedNodes) {\n const desc = await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n { objectId: resolvedNode.objectId },\n );\n const backendNodeId = desc.node.backendNodeId;\n if (typeof backendNodeId === \"number\") {\n backendNodeIds.add(backendNodeId);\n }\n }\n } finally {\n await Promise.all(\n resolvedNodes.map((resolvedNode) =>\n session\n .send(\"Runtime.releaseObject\", { objectId: resolvedNode.objectId })\n .catch(() => {}),\n ),\n );\n }\n\n return [...backendNodeIds];\n}\n\nexport async function buildFrameExclusionIntervals(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n ignoredNodesByFrame: IgnoredNodeMap,\n): Promise<ExclusionIntervalsByFrame> {\n const intervalsByFrame: ExclusionIntervalsByFrame = new Map();\n if (!ignoredNodesByFrame.size) return intervalsByFrame;\n const childFramesByParent = await resolveChildFramesByParent(page, context);\n const excludedFrames = new Set<string>();\n\n const pushInterval = (frameId: string, start: number, end: number) => {\n const intervals = intervalsByFrame.get(frameId) ?? [];\n intervals.push({ start, end });\n intervalsByFrame.set(frameId, intervals);\n };\n\n const excludeFrameSubtree = async (frameId: string): Promise<void> => {\n if (excludedFrames.has(frameId)) return;\n excludedFrames.add(frameId);\n\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, frameId);\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n const start = idx.enterByBe.get(docRootBe);\n const end = idx.exitByBe.get(docRootBe);\n if (typeof start === \"number\" && typeof end === \"number\") {\n pushInterval(frameId, start, end);\n }\n\n for (const childFrameId of listChildrenOf(context.parentByFrame, frameId)) {\n await excludeFrameSubtree(childFrameId);\n }\n };\n\n const excludeIgnoredNode = async (\n frameId: string,\n backendNodeId: number,\n ): Promise<void> => {\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const start = idx.enterByBe.get(backendNodeId);\n const end = idx.exitByBe.get(backendNodeId);\n if (typeof start !== \"number\" || typeof end !== \"number\") return;\n\n pushInterval(frameId, start, end);\n for (const childFrame of childFramesByParent.get(frameId) ?? []) {\n const hostEnter = idx.enterByBe.get(childFrame.hostBackendNodeId);\n if (typeof hostEnter !== \"number\") continue;\n if (hostEnter < start || hostEnter > end) continue;\n await excludeFrameSubtree(childFrame.childFrameId);\n }\n };\n\n for (const [frameId, backendNodeIds] of ignoredNodesByFrame.entries()) {\n for (const backendNodeId of backendNodeIds) {\n await excludeIgnoredNode(frameId, backendNodeId);\n }\n }\n\n for (const [frameId, intervals] of intervalsByFrame.entries()) {\n intervals.sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: Interval[] = [];\n for (const interval of intervals) {\n const prev = merged[merged.length - 1];\n if (!prev || interval.start > prev.end) {\n merged.push({ ...interval });\n continue;\n }\n if (interval.end > prev.end) prev.end = interval.end;\n }\n intervalsByFrame.set(frameId, merged);\n }\n\n return intervalsByFrame;\n}\n\nasync function resolveChildFramesByParent(\n page: Page,\n context: FrameContext,\n): Promise<ChildFramesByParent> {\n const childFramesByParent: ChildFramesByParent = new Map();\n\n for (const frameId of context.frames) {\n const parentId = context.parentByFrame.get(frameId);\n if (!parentId) continue;\n\n const session = parentSession(page, context.parentByFrame, frameId);\n if (!session) continue;\n\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId !== \"number\") continue;\n const childFrames = childFramesByParent.get(parentId) ?? [];\n childFrames.push({\n childFrameId: frameId,\n hostBackendNodeId: backendNodeId,\n });\n childFramesByParent.set(parentId, childFrames);\n } catch {\n continue;\n }\n }\n\n return childFramesByParent;\n}\n\nfunction makeIsIgnoredBackendNode(\n frameId: string,\n idx: SessionDomIndex | undefined,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): ((backendNodeId: number) => boolean) | undefined {\n if (!idx) return undefined;\n const intervals = exclusionIntervalsByFrame.get(frameId);\n if (!intervals?.length) return undefined;\n\n return (backendNodeId: number): boolean => {\n const enter = idx.enterByBe.get(backendNodeId);\n if (typeof enter !== \"number\") return false;\n\n let lo = 0;\n let hi = intervals.length - 1;\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const interval = intervals[mid]!;\n if (enter < interval.start) {\n hi = mid - 1;\n } else if (enter > interval.end) {\n lo = mid + 1;\n } else {\n return true;\n }\n }\n return false;\n };\n}\n\nfunction parseEncodedBackendNodeId(encodedId: string): number | undefined {\n const parts = encodedId.split(\"-\");\n if (parts.length !== 2) return undefined;\n const backendNodeId = Number(parts[1]);\n return Number.isFinite(backendNodeId) ? backendNodeId : undefined;\n}\n\nfunction ownerSessionIndexForFrame(\n page: Page,\n frameId: string,\n sessionToIndex: Map<string, SessionDomIndex>,\n): SessionDomIndex | undefined {\n const session = ownerSession(page, frameId);\n return sessionToIndex.get(session.id ?? \"root\");\n}\n\nasync function resolveFrameDocRootBackendId(\n page: Page,\n frameId: string,\n idx: SessionDomIndex,\n sameSessionAsParent: boolean,\n): Promise<number> {\n if (!sameSessionAsParent) return idx.rootBackend;\n const session = ownerSession(page, frameId);\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId === \"number\") {\n const docRootBe = idx.contentDocRootByIframe.get(backendNodeId);\n if (typeof docRootBe === \"number\") return docRootBe;\n }\n } catch {\n //\n }\n return idx.rootBackend;\n}\n\n/**\n * Step 4 – walk the frame tree (parent-first) to compute absolute prefixes for\n * every frame. The prefix is the absolute XPath of the iframe element hosting\n * the frame, so we can later convert relative XPaths into cross-frame ones.\n */\nexport async function computeFramePrefixes(\n page: Page,\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n frameIds: string[],\n): Promise<{\n absPrefix: Map<string, string>;\n iframeHostEncByChild: Map<string, string>;\n}> {\n const absPrefix = new Map<string, string>();\n const iframeHostEncByChild = new Map<string, string>();\n absPrefix.set(context.rootId, \"\");\n const included = new Set(frameIds);\n\n const queue: string[] = [];\n if (included.has(context.rootId)) {\n queue.push(context.rootId);\n }\n\n while (queue.length) {\n const parent = queue.shift()!;\n const parentAbs = absPrefix.get(parent)!;\n\n for (const child of context.frames) {\n if (!included.has(child)) continue;\n if (context.parentByFrame.get(child) !== parent) continue;\n queue.push(child);\n\n const parentSess = parentSession(page, context.parentByFrame, child);\n\n const ownerBackendNodeId = await (async () => {\n try {\n const { backendNodeId } = await parentSess.send<{\n backendNodeId?: number;\n }>(\"DOM.getFrameOwner\", { frameId: child });\n return backendNodeId;\n } catch {\n return undefined;\n }\n })();\n\n if (!ownerBackendNodeId) {\n // OOPIFs resolved via a different session inherit the parent prefix.\n absPrefix.set(child, parentAbs);\n continue;\n }\n\n const parentDom = perFrameMaps.get(parent);\n const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;\n const iframeXPath = parentDom?.xpathMap[iframeEnc];\n\n const childAbs = iframeXPath\n ? prefixXPath(parentAbs || \"/\", iframeXPath)\n : parentAbs;\n\n absPrefix.set(child, childAbs);\n iframeHostEncByChild.set(child, iframeEnc);\n }\n }\n\n return { absPrefix, iframeHostEncByChild };\n}\n\n/**\n * Step 5 – merge per-frame maps into the combined snapshot payload. We prefix\n * each frame's relative XPaths with the absolute path collected in step 4,\n * merge URL maps, and stitch text outlines by nesting child trees under the\n * encoded id of their parent iframe host.\n */\nexport function mergeFramesIntoSnapshot(\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n perFrameOutlines: Array<{ frameId: string; outline: string }>,\n absPrefix: Map<string, string>,\n iframeHostEncByChild: Map<string, string>,\n frameIds: string[],\n): HybridSnapshot {\n const combinedXpathMap: Record<string, string> = {};\n const combinedUrlMap: Record<string, string> = {};\n\n for (const frameId of frameIds) {\n const maps = perFrameMaps.get(frameId);\n if (!maps) continue;\n\n const abs = absPrefix.get(frameId) ?? \"\";\n const isRoot = abs === \"\" || abs === \"/\";\n\n if (isRoot) {\n Object.assign(combinedXpathMap, maps.xpathMap);\n Object.assign(combinedUrlMap, maps.urlMap);\n continue;\n }\n\n for (const [encId, xp] of Object.entries(maps.xpathMap)) {\n combinedXpathMap[encId] = prefixXPath(abs, xp);\n }\n Object.assign(combinedUrlMap, maps.urlMap);\n }\n\n const idToTree = new Map<string, string>();\n for (const { frameId, outline } of perFrameOutlines) {\n const parentEnc = iframeHostEncByChild.get(frameId);\n // The key is the parent iframe's encoded id so injectSubtrees can nest lines.\n if (parentEnc) idToTree.set(parentEnc, outline);\n }\n\n const rootOutline =\n perFrameOutlines.find((o) => o.frameId === context.rootId)?.outline ??\n perFrameOutlines[0]?.outline ??\n \"\";\n const combinedTree = injectSubtrees(rootOutline, idToTree);\n\n return {\n combinedTree,\n combinedXpathMap,\n combinedUrlMap,\n perFrame: perFrameOutlines.map(({ frameId, outline }) => {\n const maps = perFrameMaps.get(frameId);\n return {\n frameId,\n outline,\n xpathMap: maps?.xpathMap ?? {},\n urlMap: maps?.urlMap ?? {},\n };\n }),\n };\n}\n"]}
@@ -158,7 +158,7 @@ export async function domMapsForSession(session, frameId, pierce, encode, attemp
158
158
  const { node, xpath } = stack.pop();
159
159
  if (node.backendNodeId) {
160
160
  const encId = encode(frameId, node.backendNodeId);
161
- tagNameMap[encId] = String(node.nodeName).toLowerCase();
161
+ tagNameMap[encId] = enrichedTagName(node);
162
162
  xpathMap[encId] = xpath || "/";
163
163
  const isScrollable = node?.isScrollable === true;
164
164
  if (isScrollable)
@@ -198,33 +198,61 @@ export async function buildSessionDomIndex(session, pierce) {
198
198
  const scrollByBe = new Map();
199
199
  const docRootOf = new Map();
200
200
  const contentDocRootByIframe = new Map();
201
+ const enterByBe = new Map();
202
+ const exitByBe = new Map();
201
203
  const rootBe = root.backendNodeId;
202
- const stack = [{ node: root, xp: "/", docRootBe: rootBe }];
204
+ const stack = [
205
+ { node: root, xp: "/", docRootBe: rootBe, phase: "enter" },
206
+ ];
207
+ let dfsIndex = 0;
203
208
  while (stack.length) {
204
- const { node, xp, docRootBe } = stack.pop();
209
+ const { node, xp, docRootBe, phase } = stack.pop();
210
+ if (phase === "exit") {
211
+ if (node.backendNodeId) {
212
+ exitByBe.set(node.backendNodeId, dfsIndex++);
213
+ }
214
+ continue;
215
+ }
205
216
  if (node.backendNodeId) {
217
+ enterByBe.set(node.backendNodeId, dfsIndex++);
206
218
  absByBe.set(node.backendNodeId, xp || "/");
207
- tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());
219
+ tagByBe.set(node.backendNodeId, enrichedTagName(node));
208
220
  if (node?.isScrollable === true)
209
221
  scrollByBe.set(node.backendNodeId, true);
210
222
  docRootOf.set(node.backendNodeId, docRootBe);
211
223
  }
224
+ stack.push({ node, xp, docRootBe, phase: "exit" });
212
225
  const kids = node.children ?? [];
213
226
  if (kids.length) {
214
227
  const segs = buildChildXPathSegments(kids);
215
228
  for (let i = kids.length - 1; i >= 0; i--) {
216
229
  const child = kids[i];
217
230
  const step = segs[i];
218
- stack.push({ node: child, xp: joinXPath(xp, step), docRootBe });
231
+ stack.push({
232
+ node: child,
233
+ xp: joinXPath(xp, step),
234
+ docRootBe,
235
+ phase: "enter",
236
+ });
219
237
  }
220
238
  }
221
239
  for (const sr of node.shadowRoots ?? []) {
222
- stack.push({ node: sr, xp: joinXPath(xp, "//"), docRootBe });
240
+ stack.push({
241
+ node: sr,
242
+ xp: joinXPath(xp, "//"),
243
+ docRootBe,
244
+ phase: "enter",
245
+ });
223
246
  }
224
247
  const cd = node.contentDocument;
225
248
  if (cd && typeof cd.backendNodeId === "number") {
226
249
  contentDocRootByIframe.set(node.backendNodeId, cd.backendNodeId);
227
- stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });
250
+ stack.push({
251
+ node: cd,
252
+ xp,
253
+ docRootBe: cd.backendNodeId,
254
+ phase: "enter",
255
+ });
228
256
  }
229
257
  }
230
258
  return {
@@ -234,6 +262,8 @@ export async function buildSessionDomIndex(session, pierce) {
234
262
  scrollByBe,
235
263
  docRootOf,
236
264
  contentDocRootByIframe,
265
+ enterByBe,
266
+ exitByBe,
237
267
  };
238
268
  }
239
269
  /**
@@ -255,6 +285,29 @@ export function relativizeXPath(baseAbs, nodeAbs) {
255
285
  return abs;
256
286
  return abs;
257
287
  }
288
+ /**
289
+ * Extract an attribute value from a CDP DOM node's flat attributes array.
290
+ * Attributes are stored as [name1, value1, name2, value2, ...].
291
+ */
292
+ function getAttr(attrs, name) {
293
+ if (!attrs)
294
+ return undefined;
295
+ for (let i = 0; i < attrs.length; i += 2) {
296
+ if (attrs[i] === name)
297
+ return attrs[i + 1];
298
+ }
299
+ return undefined;
300
+ }
301
+ /** Build an enriched tag name that includes the type attribute for inputs. */
302
+ function enrichedTagName(node) {
303
+ const tag = String(node.nodeName).toLowerCase();
304
+ if (tag === "input") {
305
+ const type = getAttr(node.attributes, "type");
306
+ if (type)
307
+ return `input, ${type}`;
308
+ }
309
+ return tag;
310
+ }
258
311
  /** Find a node by backendNodeId inside a DOM.getDocument tree. */
259
312
  export function findNodeByBackendId(root, backendNodeId) {
260
313
  const stack = [root];
@@ -1 +1 @@
1
- {"version":3,"file":"domTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/domTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { StagehandDomProcessError } from \"../../../types/public/sdkErrors.js\";\nimport type { SessionDomIndex } from \"../../../types/private/snapshot.js\";\nimport {\n buildChildXPathSegments,\n joinXPath,\n normalizeXPath,\n} from \"./xpathUtils.js\";\n\n// starting from infinite depth (-1), exponentially shrink down to 1\nconst DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];\nconst DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];\n\n/** Identify CDP failures caused by deep DOM trees blowing the CBOR encoder stack. */\nfunction isCborStackError(message: string): boolean {\n return message.includes(\"CBOR: stack limit exceeded\");\n}\n\n/**\n * Determine if CDP truncated a node's children when streaming the DOM tree.\n * childNodeCount stays accurate even when `children` are omitted; we use this to\n * decide whether DOM.describeNode must be re-run for that node.\n */\nexport function shouldExpandNode(node: Protocol.DOM.Node): boolean {\n const declaredChildren = node.childNodeCount ?? 0;\n const realizedChildren = node.children?.length ?? 0;\n return declaredChildren > realizedChildren;\n}\n\n/** Merge an expanded DescribeNode payload back into the original shallow node. */\nexport function mergeDomNodes(\n target: Protocol.DOM.Node,\n source: Protocol.DOM.Node,\n): void {\n target.childNodeCount = source.childNodeCount ?? target.childNodeCount;\n target.children = source.children ?? target.children;\n target.shadowRoots = source.shadowRoots ?? target.shadowRoots;\n target.contentDocument = source.contentDocument ?? target.contentDocument;\n}\n\n/** Helper that returns every nested collection we recurse through uniformly. */\nexport function collectDomTraversalTargets(\n node: Protocol.DOM.Node,\n): Protocol.DOM.Node[] {\n const targets: Protocol.DOM.Node[] = [];\n if (node.children) targets.push(...node.children);\n if (node.shadowRoots) targets.push(...node.shadowRoots);\n if (node.contentDocument) targets.push(node.contentDocument);\n return targets;\n}\n\n/**\n * Rehydrate a truncated DOM tree by repeatedly calling DOM.describeNode with\n * decreasing depths. Any non-CBOR failure is surfaced as a StagehandDomProcessError.\n */\nexport async function hydrateDomTree(\n session: CDPSessionLike,\n root: Protocol.DOM.Node,\n pierce: boolean,\n): Promise<void> {\n const stack: Protocol.DOM.Node[] = [root];\n const expandedNodeIds = new Set<number>();\n const expandedBackendIds = new Set<number>();\n\n while (stack.length) {\n const node = stack.pop()!;\n const nodeId =\n typeof node.nodeId === \"number\" && node.nodeId > 0\n ? node.nodeId\n : undefined;\n const backendId =\n typeof node.backendNodeId === \"number\" && node.backendNodeId > 0\n ? node.backendNodeId\n : undefined;\n\n const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;\n const seenByBackend =\n !nodeId && backendId ? expandedBackendIds.has(backendId) : false;\n if (seenByNode || seenByBackend) continue;\n if (nodeId) expandedNodeIds.add(nodeId);\n else if (backendId) expandedBackendIds.add(backendId);\n\n const needsExpansion = shouldExpandNode(node);\n if (needsExpansion && (nodeId || backendId)) {\n const describeParamsBase = nodeId\n ? { nodeId }\n : { backendNodeId: backendId! };\n let expanded = false;\n for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {\n try {\n const described =\n await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n {\n ...describeParamsBase,\n depth,\n pierce,\n },\n );\n mergeDomNodes(node, described.node);\n if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {\n node.nodeId = described.node.nodeId;\n expandedNodeIds.add(described.node.nodeId);\n }\n expanded = true;\n break;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n continue;\n }\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Failed to expand DOM node ${identifier}: ${String(err)}`,\n );\n }\n }\n if (!expanded) {\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Unable to expand DOM node ${identifier} after describeNode depth retries`,\n );\n }\n }\n\n for (const child of collectDomTraversalTargets(node)) {\n stack.push(child);\n }\n }\n}\n\n/**\n * Attempt DOM.getDocument with progressively shallower depths until CBOR stops\n * complaining. When a shallower snapshot is returned we hydrate the missing\n * branches so downstream DOM traversals see the full tree shape.\n */\nexport async function getDomTreeWithFallback(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<Protocol.DOM.Node> {\n let lastCborMessage = \"\";\n\n for (const depth of DOM_DEPTH_ATTEMPTS) {\n try {\n const { root } = await session.send<{ root: Protocol.DOM.Node }>(\n \"DOM.getDocument\",\n { depth, pierce },\n );\n\n if (depth !== -1) {\n await hydrateDomTree(session, root, pierce);\n }\n\n return root;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n lastCborMessage = message;\n continue;\n }\n throw err;\n }\n }\n\n throw new StagehandDomProcessError(\n lastCborMessage\n ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}`\n : \"CDP DOM.getDocument failed after adaptive depth retries.\",\n );\n}\n\n/**\n * Build tag name and XPath maps for a single frame session.\n * EncodedId is produced by a frame-aware encoder provided by the caller.\n */\nexport async function domMapsForSession(\n session: CDPSessionLike,\n frameId: string,\n pierce: boolean,\n encode: (fid: string, backendNodeId: number) => string,\n attemptOwnerLookup = true,\n): Promise<{\n tagNameMap: Record<string, string>;\n xpathMap: Record<string, string>;\n scrollableMap: Record<string, boolean>;\n}> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n let startNode: Protocol.DOM.Node = root;\n if (attemptOwnerLookup) {\n try {\n const owner = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n const ownerBackendId = owner.backendNodeId;\n if (typeof ownerBackendId === \"number\") {\n const ownerEl = findNodeByBackendId(root, ownerBackendId);\n if (ownerEl?.contentDocument) {\n startNode = ownerEl.contentDocument;\n }\n }\n } catch {\n // OOPIF or race → keep startNode = root\n }\n }\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n\n type StackEntry = { node: Protocol.DOM.Node; xpath: string };\n const stack: StackEntry[] = [{ node: startNode, xpath: \"\" }];\n\n while (stack.length) {\n const { node, xpath } = stack.pop()!;\n\n if (node.backendNodeId) {\n const encId = encode(frameId, node.backendNodeId);\n tagNameMap[encId] = String(node.nodeName).toLowerCase();\n xpathMap[encId] = xpath || \"/\";\n const isScrollable = node?.isScrollable === true;\n if (isScrollable) scrollableMap[encId] = true;\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xpath: joinXPath(xpath, step),\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xpath: joinXPath(xpath, \"//\"),\n });\n }\n }\n\n return { tagNameMap, xpathMap, scrollableMap };\n}\n\n/**\n * Build an index of absolute XPath/tag metadata for an entire CDP session.\n * Once the index is cached, per-frame slices are derived without extra DOM\n * calls, which keeps snapshot capture linear in the number of frames.\n */\nexport async function buildSessionDomIndex(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<SessionDomIndex> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n const absByBe = new Map<number, string>();\n const tagByBe = new Map<number, string>();\n const scrollByBe = new Map<number, boolean>();\n const docRootOf = new Map<number, number>();\n const contentDocRootByIframe = new Map<number, number>();\n\n type Entry = { node: Protocol.DOM.Node; xp: string; docRootBe: number };\n const rootBe = root.backendNodeId!;\n const stack: Entry[] = [{ node: root, xp: \"/\", docRootBe: rootBe }];\n\n while (stack.length) {\n const { node, xp, docRootBe } = stack.pop()!;\n if (node.backendNodeId) {\n absByBe.set(node.backendNodeId, xp || \"/\");\n tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());\n if (node?.isScrollable === true) scrollByBe.set(node.backendNodeId, true);\n docRootOf.set(node.backendNodeId, docRootBe);\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({ node: child, xp: joinXPath(xp, step), docRootBe });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({ node: sr, xp: joinXPath(xp, \"//\"), docRootBe });\n }\n\n const cd = node.contentDocument as Protocol.DOM.Node | undefined;\n if (cd && typeof cd.backendNodeId === \"number\") {\n contentDocRootByIframe.set(node.backendNodeId!, cd.backendNodeId);\n stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });\n }\n }\n\n return {\n rootBackend: rootBe,\n absByBe,\n tagByBe,\n scrollByBe,\n docRootOf,\n contentDocRootByIframe,\n };\n}\n\n/**\n * Relativize an absolute XPath against a document root's absolute path.\n * When the node lives outside the document we return the absolute path as-is.\n */\nexport function relativizeXPath(baseAbs: string, nodeAbs: string): string {\n const base = normalizeXPath(baseAbs);\n const abs = normalizeXPath(nodeAbs);\n if (abs === base) return \"/\";\n if (abs.startsWith(base)) {\n const tail = abs.slice(base.length);\n if (!tail) return \"/\";\n return tail.startsWith(\"/\") || tail.startsWith(\"//\") ? tail : `/${tail}`;\n }\n if (base === \"/\") return abs;\n return abs;\n}\n\n/** Find a node by backendNodeId inside a DOM.getDocument tree. */\nexport function findNodeByBackendId(\n root: Protocol.DOM.Node,\n backendNodeId: number,\n): Protocol.DOM.Node | undefined {\n const stack: Protocol.DOM.Node[] = [root];\n while (stack.length) {\n const n = stack.pop()!;\n if (n.backendNodeId === backendNodeId) return n;\n if (n.children) for (const c of n.children) stack.push(c);\n if (n.shadowRoots) for (const s of n.shadowRoots) stack.push(s);\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"domTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/domTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { StagehandDomProcessError } from \"../../../types/public/sdkErrors.js\";\nimport type { SessionDomIndex } from \"../../../types/private/snapshot.js\";\nimport {\n buildChildXPathSegments,\n joinXPath,\n normalizeXPath,\n} from \"./xpathUtils.js\";\n\n// starting from infinite depth (-1), exponentially shrink down to 1\nconst DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];\nconst DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];\n\n/** Identify CDP failures caused by deep DOM trees blowing the CBOR encoder stack. */\nfunction isCborStackError(message: string): boolean {\n return message.includes(\"CBOR: stack limit exceeded\");\n}\n\n/**\n * Determine if CDP truncated a node's children when streaming the DOM tree.\n * childNodeCount stays accurate even when `children` are omitted; we use this to\n * decide whether DOM.describeNode must be re-run for that node.\n */\nexport function shouldExpandNode(node: Protocol.DOM.Node): boolean {\n const declaredChildren = node.childNodeCount ?? 0;\n const realizedChildren = node.children?.length ?? 0;\n return declaredChildren > realizedChildren;\n}\n\n/** Merge an expanded DescribeNode payload back into the original shallow node. */\nexport function mergeDomNodes(\n target: Protocol.DOM.Node,\n source: Protocol.DOM.Node,\n): void {\n target.childNodeCount = source.childNodeCount ?? target.childNodeCount;\n target.children = source.children ?? target.children;\n target.shadowRoots = source.shadowRoots ?? target.shadowRoots;\n target.contentDocument = source.contentDocument ?? target.contentDocument;\n}\n\n/** Helper that returns every nested collection we recurse through uniformly. */\nexport function collectDomTraversalTargets(\n node: Protocol.DOM.Node,\n): Protocol.DOM.Node[] {\n const targets: Protocol.DOM.Node[] = [];\n if (node.children) targets.push(...node.children);\n if (node.shadowRoots) targets.push(...node.shadowRoots);\n if (node.contentDocument) targets.push(node.contentDocument);\n return targets;\n}\n\n/**\n * Rehydrate a truncated DOM tree by repeatedly calling DOM.describeNode with\n * decreasing depths. Any non-CBOR failure is surfaced as a StagehandDomProcessError.\n */\nexport async function hydrateDomTree(\n session: CDPSessionLike,\n root: Protocol.DOM.Node,\n pierce: boolean,\n): Promise<void> {\n const stack: Protocol.DOM.Node[] = [root];\n const expandedNodeIds = new Set<number>();\n const expandedBackendIds = new Set<number>();\n\n while (stack.length) {\n const node = stack.pop()!;\n const nodeId =\n typeof node.nodeId === \"number\" && node.nodeId > 0\n ? node.nodeId\n : undefined;\n const backendId =\n typeof node.backendNodeId === \"number\" && node.backendNodeId > 0\n ? node.backendNodeId\n : undefined;\n\n const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;\n const seenByBackend =\n !nodeId && backendId ? expandedBackendIds.has(backendId) : false;\n if (seenByNode || seenByBackend) continue;\n if (nodeId) expandedNodeIds.add(nodeId);\n else if (backendId) expandedBackendIds.add(backendId);\n\n const needsExpansion = shouldExpandNode(node);\n if (needsExpansion && (nodeId || backendId)) {\n const describeParamsBase = nodeId\n ? { nodeId }\n : { backendNodeId: backendId! };\n let expanded = false;\n for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {\n try {\n const described =\n await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n {\n ...describeParamsBase,\n depth,\n pierce,\n },\n );\n mergeDomNodes(node, described.node);\n if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {\n node.nodeId = described.node.nodeId;\n expandedNodeIds.add(described.node.nodeId);\n }\n expanded = true;\n break;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n continue;\n }\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Failed to expand DOM node ${identifier}: ${String(err)}`,\n );\n }\n }\n if (!expanded) {\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Unable to expand DOM node ${identifier} after describeNode depth retries`,\n );\n }\n }\n\n for (const child of collectDomTraversalTargets(node)) {\n stack.push(child);\n }\n }\n}\n\n/**\n * Attempt DOM.getDocument with progressively shallower depths until CBOR stops\n * complaining. When a shallower snapshot is returned we hydrate the missing\n * branches so downstream DOM traversals see the full tree shape.\n */\nexport async function getDomTreeWithFallback(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<Protocol.DOM.Node> {\n let lastCborMessage = \"\";\n\n for (const depth of DOM_DEPTH_ATTEMPTS) {\n try {\n const { root } = await session.send<{ root: Protocol.DOM.Node }>(\n \"DOM.getDocument\",\n { depth, pierce },\n );\n\n if (depth !== -1) {\n await hydrateDomTree(session, root, pierce);\n }\n\n return root;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n lastCborMessage = message;\n continue;\n }\n throw err;\n }\n }\n\n throw new StagehandDomProcessError(\n lastCborMessage\n ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}`\n : \"CDP DOM.getDocument failed after adaptive depth retries.\",\n );\n}\n\n/**\n * Build tag name and XPath maps for a single frame session.\n * EncodedId is produced by a frame-aware encoder provided by the caller.\n */\nexport async function domMapsForSession(\n session: CDPSessionLike,\n frameId: string,\n pierce: boolean,\n encode: (fid: string, backendNodeId: number) => string,\n attemptOwnerLookup = true,\n): Promise<{\n tagNameMap: Record<string, string>;\n xpathMap: Record<string, string>;\n scrollableMap: Record<string, boolean>;\n}> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n let startNode: Protocol.DOM.Node = root;\n if (attemptOwnerLookup) {\n try {\n const owner = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n const ownerBackendId = owner.backendNodeId;\n if (typeof ownerBackendId === \"number\") {\n const ownerEl = findNodeByBackendId(root, ownerBackendId);\n if (ownerEl?.contentDocument) {\n startNode = ownerEl.contentDocument;\n }\n }\n } catch {\n // OOPIF or race → keep startNode = root\n }\n }\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n\n type StackEntry = { node: Protocol.DOM.Node; xpath: string };\n const stack: StackEntry[] = [{ node: startNode, xpath: \"\" }];\n\n while (stack.length) {\n const { node, xpath } = stack.pop()!;\n\n if (node.backendNodeId) {\n const encId = encode(frameId, node.backendNodeId);\n tagNameMap[encId] = enrichedTagName(node);\n xpathMap[encId] = xpath || \"/\";\n const isScrollable = node?.isScrollable === true;\n if (isScrollable) scrollableMap[encId] = true;\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xpath: joinXPath(xpath, step),\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xpath: joinXPath(xpath, \"//\"),\n });\n }\n }\n\n return { tagNameMap, xpathMap, scrollableMap };\n}\n\n/**\n * Build an index of absolute XPath/tag metadata for an entire CDP session.\n * Once the index is cached, per-frame slices are derived without extra DOM\n * calls, which keeps snapshot capture linear in the number of frames.\n */\nexport async function buildSessionDomIndex(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<SessionDomIndex> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n const absByBe = new Map<number, string>();\n const tagByBe = new Map<number, string>();\n const scrollByBe = new Map<number, boolean>();\n const docRootOf = new Map<number, number>();\n const contentDocRootByIframe = new Map<number, number>();\n const enterByBe = new Map<number, number>();\n const exitByBe = new Map<number, number>();\n\n type Entry = {\n node: Protocol.DOM.Node;\n xp: string;\n docRootBe: number;\n phase: \"enter\" | \"exit\";\n };\n const rootBe = root.backendNodeId!;\n const stack: Entry[] = [\n { node: root, xp: \"/\", docRootBe: rootBe, phase: \"enter\" },\n ];\n let dfsIndex = 0;\n\n while (stack.length) {\n const { node, xp, docRootBe, phase } = stack.pop()!;\n if (phase === \"exit\") {\n if (node.backendNodeId) {\n exitByBe.set(node.backendNodeId, dfsIndex++);\n }\n continue;\n }\n\n if (node.backendNodeId) {\n enterByBe.set(node.backendNodeId, dfsIndex++);\n absByBe.set(node.backendNodeId, xp || \"/\");\n tagByBe.set(node.backendNodeId, enrichedTagName(node));\n if (node?.isScrollable === true) scrollByBe.set(node.backendNodeId, true);\n docRootOf.set(node.backendNodeId, docRootBe);\n }\n\n stack.push({ node, xp, docRootBe, phase: \"exit\" });\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xp: joinXPath(xp, step),\n docRootBe,\n phase: \"enter\",\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xp: joinXPath(xp, \"//\"),\n docRootBe,\n phase: \"enter\",\n });\n }\n\n const cd = node.contentDocument as Protocol.DOM.Node | undefined;\n if (cd && typeof cd.backendNodeId === \"number\") {\n contentDocRootByIframe.set(node.backendNodeId!, cd.backendNodeId);\n stack.push({\n node: cd,\n xp,\n docRootBe: cd.backendNodeId,\n phase: \"enter\",\n });\n }\n }\n\n return {\n rootBackend: rootBe,\n absByBe,\n tagByBe,\n scrollByBe,\n docRootOf,\n contentDocRootByIframe,\n enterByBe,\n exitByBe,\n };\n}\n\n/**\n * Relativize an absolute XPath against a document root's absolute path.\n * When the node lives outside the document we return the absolute path as-is.\n */\nexport function relativizeXPath(baseAbs: string, nodeAbs: string): string {\n const base = normalizeXPath(baseAbs);\n const abs = normalizeXPath(nodeAbs);\n if (abs === base) return \"/\";\n if (abs.startsWith(base)) {\n const tail = abs.slice(base.length);\n if (!tail) return \"/\";\n return tail.startsWith(\"/\") || tail.startsWith(\"//\") ? tail : `/${tail}`;\n }\n if (base === \"/\") return abs;\n return abs;\n}\n\n/**\n * Extract an attribute value from a CDP DOM node's flat attributes array.\n * Attributes are stored as [name1, value1, name2, value2, ...].\n */\nfunction getAttr(\n attrs: string[] | undefined,\n name: string,\n): string | undefined {\n if (!attrs) return undefined;\n for (let i = 0; i < attrs.length; i += 2) {\n if (attrs[i] === name) return attrs[i + 1];\n }\n return undefined;\n}\n\n/** Build an enriched tag name that includes the type attribute for inputs. */\nfunction enrichedTagName(node: Protocol.DOM.Node): string {\n const tag = String(node.nodeName).toLowerCase();\n if (tag === \"input\") {\n const type = getAttr(node.attributes, \"type\");\n if (type) return `input, ${type}`;\n }\n return tag;\n}\n\n/** Find a node by backendNodeId inside a DOM.getDocument tree. */\nexport function findNodeByBackendId(\n root: Protocol.DOM.Node,\n backendNodeId: number,\n): Protocol.DOM.Node | undefined {\n const stack: Protocol.DOM.Node[] = [root];\n while (stack.length) {\n const n = stack.pop()!;\n if (n.backendNodeId === backendNodeId) return n;\n if (n.children) for (const c of n.children) stack.push(c);\n if (n.shadowRoots) for (const s of n.shadowRoots) stack.push(s);\n }\n return undefined;\n}\n"]}
@@ -141,14 +141,25 @@ export class FrameRegistry {
141
141
  seedFromFrameTree(sessionId, frameTree) {
142
142
  const walk = (tree, parent) => {
143
143
  this.ensureNode(tree.frame.id);
144
+ const info = this.frames.get(tree.frame.id);
145
+ const previousParent = info.parentId;
146
+ const nextParent = parent ?? tree.frame.parentId ?? previousParent ?? null;
144
147
  // topology
145
- this.frames.get(tree.frame.id).parentId = parent;
146
- if (parent)
147
- this.frames.get(parent).children.add(tree.frame.id);
148
+ if (previousParent && previousParent !== nextParent) {
149
+ this.frames.get(previousParent)?.children.delete(tree.frame.id);
150
+ }
151
+ info.parentId = nextParent;
152
+ if (nextParent) {
153
+ this.ensureNode(nextParent);
154
+ this.frames.get(nextParent).children.add(tree.frame.id);
155
+ }
148
156
  // last-seen frame
149
- this.frames.get(tree.frame.id).lastSeen = tree.frame;
157
+ info.lastSeen =
158
+ nextParent && !tree.frame.parentId
159
+ ? { ...tree.frame, parentId: nextParent }
160
+ : tree.frame;
150
161
  // ownership (only if unknown)
151
- if (!this.frames.get(tree.frame.id).ownerSessionId) {
162
+ if (!info.ownerSessionId) {
152
163
  this.setOwnerSessionIdInternal(tree.frame.id, sessionId);
153
164
  }
154
165
  for (const c of tree.childFrames ?? [])
@@ -1 +1 @@
1
- {"version":3,"file":"frameRegistry.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/frameRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/frameRegistry.ts\nimport type { Protocol } from \"devtools-protocol\";\n\n/**\n * FrameRegistry\n *\n * Purpose:\n * A single, authoritative source of truth for **both**:\n * 1) Frame topology (parent/children, current main/root id, last-seen CDP `Frame`)\n * 2) Frame → Session ownership (which CDP session owns a given frameId)\n * 3) Optional iframe-owner metadata (backendNodeId of the <iframe> element in the parent doc)\n *\n *\n * Model:\n * - This class is **CDP-agnostic**; it stores **sessionId strings** (not session objects).\n * - Context bridges (wiring Target/Page events) must call the mutators below (onAttached,\n * onNavigated, onDetached, adoptChildSession, seedFromFrameTree, setOwnerBackendNodeId).\n * - Consumers ask read APIs (getOwnerSessionId, getParent, asProtocolFrameTree, listAll, …)\n * and never probe ownership at run time.\n */\n\ntype FrameId = string;\ntype SessionId = string;\n\ntype FrameInfo = {\n /** Parent frame id, or null for root */\n parentId: FrameId | null;\n /** Children frame ids (direct) */\n children: Set<FrameId>;\n /** Last-seen CDP Frame metadata for this id (may be a shell if never seen) */\n lastSeen?: Protocol.Page.Frame;\n\n /** Owning session id (CDP child session for OOPIF, top-level session for same-process) */\n ownerSessionId?: SessionId;\n\n /**\n * The backendNodeId of the <iframe> element **in the parent document** that hosts this frame.\n * Useful for building absolute XPath prefixes or DOM scoping in the parent session.\n */\n ownerBackendNodeId?: number;\n};\n\n/** Minimal “shell” CDP frame used when we haven’t yet seen a real Frame from events. */\nfunction shellFrame(id: FrameId): Protocol.Page.Frame {\n return {\n id,\n loaderId: \"\",\n url: \"\",\n domainAndRegistry: \"\",\n securityOrigin: \"\",\n mimeType: \"text/html\",\n secureContextType: \"InsecureScheme\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n } as Protocol.Page.Frame;\n}\n\nexport class FrameRegistry {\n /** Owner target id (top-level target); informational only */\n private readonly ownerTargetId: string;\n\n /** Current main/root frame id (changes on root swaps) */\n private rootFrameId: FrameId;\n\n /** frameId → FrameInfo */\n private frames = new Map<FrameId, FrameInfo>();\n\n /** sessionId → Set<frameId> (inverse map for diagnostics/fast membership checks) */\n private framesBySession = new Map<SessionId, Set<FrameId>>();\n\n constructor(ownerTargetId: string, mainFrameId: FrameId) {\n this.ownerTargetId = ownerTargetId;\n this.rootFrameId = mainFrameId;\n this.ensureNode(mainFrameId);\n }\n\n // ---------------------- Mutators (called by Context/Page bridges) ----------------------\n\n /**\n * Record that a frame attached. If `parentId` is null and `frameId` differs from the current\n * root, this is a root swap and we rename the root id.\n *\n * IMPORTANT: The emitter's `sessionId` is the **owner** for the new/attached frame.\n */\n onFrameAttached(\n frameId: FrameId,\n parentId: FrameId | null,\n sessionId: SessionId,\n ): void {\n // Root swap (parentId === null for main frames).\n if (!parentId && frameId !== this.rootFrameId) {\n this.renameNodeId(this.rootFrameId, frameId);\n this.rootFrameId = frameId;\n // ownership moves to this session as well\n this.setOwnerSessionIdInternal(frameId, sessionId);\n return;\n }\n\n // Normal attach\n this.ensureNode(frameId);\n if (parentId) this.ensureNode(parentId);\n\n const info = this.frames.get(frameId)!;\n info.parentId = parentId ?? null;\n\n if (parentId) {\n this.frames.get(parentId)!.children.add(frameId);\n }\n\n // Ownership: the session that emitted frameAttached owns this frame.\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record a navigation with the full CDP `Frame`. Also updates ownership based on the emitting\n * session id. Handles root swap if the navigated frame is the new main (no parentId).\n */\n onFrameNavigated(frame: Protocol.Page.Frame, sessionId: SessionId): void {\n this.ensureNode(frame.id);\n const info = this.frames.get(frame.id)!;\n info.lastSeen = frame;\n\n // Ownership follows the session that reported the navigation\n this.setOwnerSessionIdInternal(frame.id, sessionId);\n\n // If this frame has no parent, it might be the (new) main/root\n if (!(\"parentId\" in frame) || !frame.parentId) {\n if (frame.id !== this.rootFrameId) {\n // carry ordinal semantics by renaming the root id\n this.renameNodeId(this.rootFrameId, frame.id);\n this.rootFrameId = frame.id;\n }\n }\n }\n\n onNavigatedWithinDocument(\n frameId: FrameId,\n url: string,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n const lastSeen = info.lastSeen ?? shellFrame(frameId);\n info.lastSeen = { ...lastSeen, url };\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record that a frame detached. If `reason !== \"swap\"`, remove the subtree from the graph,\n * and clean the inverse maps. For “swap” we keep the node to preserve continuity.\n */\n onFrameDetached(\n frameId: FrameId,\n reason: \"remove\" | \"swap\" | string = \"remove\",\n ): void {\n if (reason === \"swap\") return;\n\n // Collect subtree starting from frameId.\n const toRemove: FrameId[] = [];\n const collect = (fid: FrameId) => {\n toRemove.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) collect(k);\n };\n collect(frameId);\n\n // Remove nodes, fix parents and inverse maps\n for (const fid of toRemove) {\n const info = this.frames.get(fid);\n if (!info) continue;\n\n // unlink from parent\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n p?.children.delete(fid);\n }\n\n // unlink inverse session map\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n bag?.delete(fid);\n if (bag && bag.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n this.frames.delete(fid);\n }\n\n // Guard root if we removed it; assign a placeholder root if needed\n if (!this.frames.has(this.rootFrameId)) {\n // Choose an arbitrary remaining node as root\n const iter = this.frames.keys().next();\n if (!iter.done) this.rootFrameId = iter.value;\n }\n }\n\n /**\n * An adopted OOPIF child session was created whose **main** frame id equals the parent iframe’s frameId.\n * We mark the entire child subtree as owned by `childSessionId`.\n * (Topology edges remain aligned by the parent session’s `frameAttached` events.)\n */\n adoptChildSession(\n childSessionId: SessionId,\n childMainFrameId: FrameId,\n ): void {\n // The child session will emit its own navigations/attachments; as a seed,\n // mark the root frame as owned by the child session.\n this.setOwnerSessionIdInternal(childMainFrameId, childSessionId);\n }\n\n /**\n * Seed topology and ownership from an existing `Page.getFrameTree` snapshot, typically right after\n * a session is attached. This is a best-effort: we record frames and set the provided `sessionId`\n * as owner for the subtree **if** an owner isn't already set.\n */\n seedFromFrameTree(\n sessionId: SessionId,\n frameTree: Protocol.Page.FrameTree,\n ): void {\n const walk = (tree: Protocol.Page.FrameTree, parent: FrameId | null) => {\n this.ensureNode(tree.frame.id);\n // topology\n this.frames.get(tree.frame.id)!.parentId = parent;\n if (parent) this.frames.get(parent)!.children.add(tree.frame.id);\n // last-seen frame\n this.frames.get(tree.frame.id)!.lastSeen = tree.frame;\n // ownership (only if unknown)\n if (!this.frames.get(tree.frame.id)!.ownerSessionId) {\n this.setOwnerSessionIdInternal(tree.frame.id, sessionId);\n }\n for (const c of tree.childFrames ?? []) walk(c, tree.frame.id);\n };\n walk(frameTree, null);\n }\n\n /**\n * Set the backendNodeId of the `<iframe>` element for a child frame **as seen from its parent**.\n * This is useful for building absolute XPath prefixes later (from the parent document).\n */\n setOwnerBackendNodeId(childFrameId: FrameId, backendNodeId: number): void {\n this.ensureNode(childFrameId);\n this.frames.get(childFrameId)!.ownerBackendNodeId = backendNodeId;\n }\n\n // ---------------------- Readers (consumed by Page/snapshot/locators) ----------------------\n\n mainFrameId(): FrameId {\n return this.rootFrameId;\n }\n\n /**\n * Return the owner session id for this frame. If unknown, returns `undefined`.\n */\n getOwnerSessionId(frameId: FrameId): SessionId | undefined {\n return this.frames.get(frameId)?.ownerSessionId;\n }\n\n /**\n * Return the owner backendNodeId (iframe element) if recorded.\n * This is in the **parent** document; pair it with `getParent`.\n */\n getOwnerBackendNodeId(frameId: FrameId): number | undefined {\n return this.frames.get(frameId)?.ownerBackendNodeId;\n }\n\n /**\n * Return the parent frame id, or null for root/unknown.\n */\n getParent(frameId: FrameId): FrameId | null {\n return this.frames.get(frameId)?.parentId ?? null;\n }\n\n /**\n * List frame ids in root-first DFS order (same shape as CDP’s FrameTree traversal).\n */\n listAllFrames(): FrameId[] {\n const out: FrameId[] = [];\n const dfs = (fid: FrameId) => {\n out.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) dfs(k);\n };\n if (this.frames.has(this.rootFrameId)) dfs(this.rootFrameId);\n return out;\n }\n\n /**\n * Serialize to `Protocol.Page.FrameTree` starting at the given root id (typically mainFrameId()).\n */\n asProtocolFrameTree(rootId: FrameId): Protocol.Page.FrameTree {\n const build = (fid: FrameId): Protocol.Page.FrameTree => {\n const info = this.frames.get(fid);\n const frame = info?.lastSeen ?? shellFrame(fid);\n\n const kids = info?.children ?? new Set<FrameId>();\n const childFrames = kids.size\n ? [...kids].map((k) => build(k))\n : undefined;\n\n return childFrames ? { frame, childFrames } : { frame };\n };\n\n return build(rootId);\n }\n\n /**\n * For diagnostics: return the current owner sessions for a frame id (0..n),\n * usually 0 or 1, but helpful to see potential inconsistencies during wiring.\n */\n sessionsForFrame(frameId: FrameId): SessionId[] {\n const info = this.frames.get(frameId);\n return info?.ownerSessionId ? [info.ownerSessionId] : [];\n }\n\n /**\n * For diagnostics: return current frame set per session.\n */\n framesForSession(sessionId: SessionId): FrameId[] {\n return [...(this.framesBySession.get(sessionId) ?? new Set())];\n }\n\n // ---------------------- Internal helpers ----------------------\n\n private ensureNode(fid: FrameId): void {\n if (this.frames.has(fid)) return;\n this.frames.set(fid, {\n parentId: null,\n children: new Set<FrameId>(),\n lastSeen: shellFrame(fid),\n ownerSessionId: undefined,\n ownerBackendNodeId: undefined,\n });\n }\n\n private renameNodeId(oldId: FrameId, newId: FrameId): void {\n if (oldId === newId) return;\n this.ensureNode(oldId);\n\n const info = this.frames.get(oldId)!;\n\n // Move info under new id\n this.frames.delete(oldId);\n this.frames.set(newId, { ...info });\n\n // Fix parent’s children set\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n if (p) {\n p.children.delete(oldId);\n p.children.add(newId);\n }\n }\n\n // Fix children’s parent pointers\n for (const c of info.children) {\n const ci = this.frames.get(c);\n if (ci) ci.parentId = newId;\n }\n\n // Fix inverse map (session -> frames)\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n if (bag) {\n bag.delete(oldId);\n bag.add(newId);\n }\n }\n\n // If root moved, keep the root id updated is handled by caller\n }\n\n private setOwnerSessionIdInternal(\n frameId: FrameId,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n\n // If the owner is unchanged, do nothing\n if (info.ownerSessionId === sessionId) return;\n\n // Remove from previous owner bag\n if (info.ownerSessionId) {\n const prev = this.framesBySession.get(info.ownerSessionId);\n prev?.delete(frameId);\n if (prev && prev.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n // Set new owner and update bag\n info.ownerSessionId = sessionId;\n const bag = this.framesBySession.get(sessionId) ?? new Set<FrameId>();\n bag.add(frameId);\n this.framesBySession.set(sessionId, bag);\n }\n}\n"]}
1
+ {"version":3,"file":"frameRegistry.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/frameRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/frameRegistry.ts\nimport type { Protocol } from \"devtools-protocol\";\n\n/**\n * FrameRegistry\n *\n * Purpose:\n * A single, authoritative source of truth for **both**:\n * 1) Frame topology (parent/children, current main/root id, last-seen CDP `Frame`)\n * 2) Frame → Session ownership (which CDP session owns a given frameId)\n * 3) Optional iframe-owner metadata (backendNodeId of the <iframe> element in the parent doc)\n *\n *\n * Model:\n * - This class is **CDP-agnostic**; it stores **sessionId strings** (not session objects).\n * - Context bridges (wiring Target/Page events) must call the mutators below (onAttached,\n * onNavigated, onDetached, adoptChildSession, seedFromFrameTree, setOwnerBackendNodeId).\n * - Consumers ask read APIs (getOwnerSessionId, getParent, asProtocolFrameTree, listAll, …)\n * and never probe ownership at run time.\n */\n\ntype FrameId = string;\ntype SessionId = string;\n\ntype FrameInfo = {\n /** Parent frame id, or null for root */\n parentId: FrameId | null;\n /** Children frame ids (direct) */\n children: Set<FrameId>;\n /** Last-seen CDP Frame metadata for this id (may be a shell if never seen) */\n lastSeen?: Protocol.Page.Frame;\n\n /** Owning session id (CDP child session for OOPIF, top-level session for same-process) */\n ownerSessionId?: SessionId;\n\n /**\n * The backendNodeId of the <iframe> element **in the parent document** that hosts this frame.\n * Useful for building absolute XPath prefixes or DOM scoping in the parent session.\n */\n ownerBackendNodeId?: number;\n};\n\n/** Minimal “shell” CDP frame used when we haven’t yet seen a real Frame from events. */\nfunction shellFrame(id: FrameId): Protocol.Page.Frame {\n return {\n id,\n loaderId: \"\",\n url: \"\",\n domainAndRegistry: \"\",\n securityOrigin: \"\",\n mimeType: \"text/html\",\n secureContextType: \"InsecureScheme\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n } as Protocol.Page.Frame;\n}\n\nexport class FrameRegistry {\n /** Owner target id (top-level target); informational only */\n private readonly ownerTargetId: string;\n\n /** Current main/root frame id (changes on root swaps) */\n private rootFrameId: FrameId;\n\n /** frameId → FrameInfo */\n private frames = new Map<FrameId, FrameInfo>();\n\n /** sessionId → Set<frameId> (inverse map for diagnostics/fast membership checks) */\n private framesBySession = new Map<SessionId, Set<FrameId>>();\n\n constructor(ownerTargetId: string, mainFrameId: FrameId) {\n this.ownerTargetId = ownerTargetId;\n this.rootFrameId = mainFrameId;\n this.ensureNode(mainFrameId);\n }\n\n // ---------------------- Mutators (called by Context/Page bridges) ----------------------\n\n /**\n * Record that a frame attached. If `parentId` is null and `frameId` differs from the current\n * root, this is a root swap and we rename the root id.\n *\n * IMPORTANT: The emitter's `sessionId` is the **owner** for the new/attached frame.\n */\n onFrameAttached(\n frameId: FrameId,\n parentId: FrameId | null,\n sessionId: SessionId,\n ): void {\n // Root swap (parentId === null for main frames).\n if (!parentId && frameId !== this.rootFrameId) {\n this.renameNodeId(this.rootFrameId, frameId);\n this.rootFrameId = frameId;\n // ownership moves to this session as well\n this.setOwnerSessionIdInternal(frameId, sessionId);\n return;\n }\n\n // Normal attach\n this.ensureNode(frameId);\n if (parentId) this.ensureNode(parentId);\n\n const info = this.frames.get(frameId)!;\n info.parentId = parentId ?? null;\n\n if (parentId) {\n this.frames.get(parentId)!.children.add(frameId);\n }\n\n // Ownership: the session that emitted frameAttached owns this frame.\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record a navigation with the full CDP `Frame`. Also updates ownership based on the emitting\n * session id. Handles root swap if the navigated frame is the new main (no parentId).\n */\n onFrameNavigated(frame: Protocol.Page.Frame, sessionId: SessionId): void {\n this.ensureNode(frame.id);\n const info = this.frames.get(frame.id)!;\n info.lastSeen = frame;\n\n // Ownership follows the session that reported the navigation\n this.setOwnerSessionIdInternal(frame.id, sessionId);\n\n // If this frame has no parent, it might be the (new) main/root\n if (!(\"parentId\" in frame) || !frame.parentId) {\n if (frame.id !== this.rootFrameId) {\n // carry ordinal semantics by renaming the root id\n this.renameNodeId(this.rootFrameId, frame.id);\n this.rootFrameId = frame.id;\n }\n }\n }\n\n onNavigatedWithinDocument(\n frameId: FrameId,\n url: string,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n const lastSeen = info.lastSeen ?? shellFrame(frameId);\n info.lastSeen = { ...lastSeen, url };\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record that a frame detached. If `reason !== \"swap\"`, remove the subtree from the graph,\n * and clean the inverse maps. For “swap” we keep the node to preserve continuity.\n */\n onFrameDetached(\n frameId: FrameId,\n reason: \"remove\" | \"swap\" | string = \"remove\",\n ): void {\n if (reason === \"swap\") return;\n\n // Collect subtree starting from frameId.\n const toRemove: FrameId[] = [];\n const collect = (fid: FrameId) => {\n toRemove.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) collect(k);\n };\n collect(frameId);\n\n // Remove nodes, fix parents and inverse maps\n for (const fid of toRemove) {\n const info = this.frames.get(fid);\n if (!info) continue;\n\n // unlink from parent\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n p?.children.delete(fid);\n }\n\n // unlink inverse session map\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n bag?.delete(fid);\n if (bag && bag.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n this.frames.delete(fid);\n }\n\n // Guard root if we removed it; assign a placeholder root if needed\n if (!this.frames.has(this.rootFrameId)) {\n // Choose an arbitrary remaining node as root\n const iter = this.frames.keys().next();\n if (!iter.done) this.rootFrameId = iter.value;\n }\n }\n\n /**\n * An adopted OOPIF child session was created whose **main** frame id equals the parent iframe’s frameId.\n * We mark the entire child subtree as owned by `childSessionId`.\n * (Topology edges remain aligned by the parent session’s `frameAttached` events.)\n */\n adoptChildSession(\n childSessionId: SessionId,\n childMainFrameId: FrameId,\n ): void {\n // The child session will emit its own navigations/attachments; as a seed,\n // mark the root frame as owned by the child session.\n this.setOwnerSessionIdInternal(childMainFrameId, childSessionId);\n }\n\n /**\n * Seed topology and ownership from an existing `Page.getFrameTree` snapshot, typically right after\n * a session is attached. This is a best-effort: we record frames and set the provided `sessionId`\n * as owner for the subtree **if** an owner isn't already set.\n */\n seedFromFrameTree(\n sessionId: SessionId,\n frameTree: Protocol.Page.FrameTree,\n ): void {\n const walk = (tree: Protocol.Page.FrameTree, parent: FrameId | null) => {\n this.ensureNode(tree.frame.id);\n const info = this.frames.get(tree.frame.id)!;\n const previousParent = info.parentId;\n const nextParent =\n parent ?? tree.frame.parentId ?? previousParent ?? null;\n\n // topology\n if (previousParent && previousParent !== nextParent) {\n this.frames.get(previousParent)?.children.delete(tree.frame.id);\n }\n info.parentId = nextParent;\n if (nextParent) {\n this.ensureNode(nextParent);\n this.frames.get(nextParent)!.children.add(tree.frame.id);\n }\n // last-seen frame\n info.lastSeen =\n nextParent && !tree.frame.parentId\n ? { ...tree.frame, parentId: nextParent }\n : tree.frame;\n // ownership (only if unknown)\n if (!info.ownerSessionId) {\n this.setOwnerSessionIdInternal(tree.frame.id, sessionId);\n }\n for (const c of tree.childFrames ?? []) walk(c, tree.frame.id);\n };\n walk(frameTree, null);\n }\n\n /**\n * Set the backendNodeId of the `<iframe>` element for a child frame **as seen from its parent**.\n * This is useful for building absolute XPath prefixes later (from the parent document).\n */\n setOwnerBackendNodeId(childFrameId: FrameId, backendNodeId: number): void {\n this.ensureNode(childFrameId);\n this.frames.get(childFrameId)!.ownerBackendNodeId = backendNodeId;\n }\n\n // ---------------------- Readers (consumed by Page/snapshot/locators) ----------------------\n\n mainFrameId(): FrameId {\n return this.rootFrameId;\n }\n\n /**\n * Return the owner session id for this frame. If unknown, returns `undefined`.\n */\n getOwnerSessionId(frameId: FrameId): SessionId | undefined {\n return this.frames.get(frameId)?.ownerSessionId;\n }\n\n /**\n * Return the owner backendNodeId (iframe element) if recorded.\n * This is in the **parent** document; pair it with `getParent`.\n */\n getOwnerBackendNodeId(frameId: FrameId): number | undefined {\n return this.frames.get(frameId)?.ownerBackendNodeId;\n }\n\n /**\n * Return the parent frame id, or null for root/unknown.\n */\n getParent(frameId: FrameId): FrameId | null {\n return this.frames.get(frameId)?.parentId ?? null;\n }\n\n /**\n * List frame ids in root-first DFS order (same shape as CDP’s FrameTree traversal).\n */\n listAllFrames(): FrameId[] {\n const out: FrameId[] = [];\n const dfs = (fid: FrameId) => {\n out.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) dfs(k);\n };\n if (this.frames.has(this.rootFrameId)) dfs(this.rootFrameId);\n return out;\n }\n\n /**\n * Serialize to `Protocol.Page.FrameTree` starting at the given root id (typically mainFrameId()).\n */\n asProtocolFrameTree(rootId: FrameId): Protocol.Page.FrameTree {\n const build = (fid: FrameId): Protocol.Page.FrameTree => {\n const info = this.frames.get(fid);\n const frame = info?.lastSeen ?? shellFrame(fid);\n\n const kids = info?.children ?? new Set<FrameId>();\n const childFrames = kids.size\n ? [...kids].map((k) => build(k))\n : undefined;\n\n return childFrames ? { frame, childFrames } : { frame };\n };\n\n return build(rootId);\n }\n\n /**\n * For diagnostics: return the current owner sessions for a frame id (0..n),\n * usually 0 or 1, but helpful to see potential inconsistencies during wiring.\n */\n sessionsForFrame(frameId: FrameId): SessionId[] {\n const info = this.frames.get(frameId);\n return info?.ownerSessionId ? [info.ownerSessionId] : [];\n }\n\n /**\n * For diagnostics: return current frame set per session.\n */\n framesForSession(sessionId: SessionId): FrameId[] {\n return [...(this.framesBySession.get(sessionId) ?? new Set())];\n }\n\n // ---------------------- Internal helpers ----------------------\n\n private ensureNode(fid: FrameId): void {\n if (this.frames.has(fid)) return;\n this.frames.set(fid, {\n parentId: null,\n children: new Set<FrameId>(),\n lastSeen: shellFrame(fid),\n ownerSessionId: undefined,\n ownerBackendNodeId: undefined,\n });\n }\n\n private renameNodeId(oldId: FrameId, newId: FrameId): void {\n if (oldId === newId) return;\n this.ensureNode(oldId);\n\n const info = this.frames.get(oldId)!;\n\n // Move info under new id\n this.frames.delete(oldId);\n this.frames.set(newId, { ...info });\n\n // Fix parent’s children set\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n if (p) {\n p.children.delete(oldId);\n p.children.add(newId);\n }\n }\n\n // Fix children’s parent pointers\n for (const c of info.children) {\n const ci = this.frames.get(c);\n if (ci) ci.parentId = newId;\n }\n\n // Fix inverse map (session -> frames)\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n if (bag) {\n bag.delete(oldId);\n bag.add(newId);\n }\n }\n\n // If root moved, keep the root id updated is handled by caller\n }\n\n private setOwnerSessionIdInternal(\n frameId: FrameId,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n\n // If the owner is unchanged, do nothing\n if (info.ownerSessionId === sessionId) return;\n\n // Remove from previous owner bag\n if (info.ownerSessionId) {\n const prev = this.framesBySession.get(info.ownerSessionId);\n prev?.delete(frameId);\n if (prev && prev.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n // Set new owner and update bag\n info.ownerSessionId = sessionId;\n const bag = this.framesBySession.get(sessionId) ?? new Set<FrameId>();\n bag.add(frameId);\n this.framesBySession.set(sessionId, bag);\n }\n}\n"]}
@@ -111,6 +111,7 @@ export declare class V3 {
111
111
  private mergeAgentMetricsWithLocalFallback;
112
112
  private updateAgentMetricsFromUsage;
113
113
  private resolveLlmClient;
114
+ private resolveDefaultAgentMode;
114
115
  private beginAgentReplayRecording;
115
116
  private endAgentReplayRecording;
116
117
  private discardAgentReplayRecording;