@xbrowser/cli 1.1.2 → 1.2.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.
@@ -282,6 +282,22 @@ function sleep2(ms) {
282
282
  return new Promise((resolve) => setTimeout(resolve, ms));
283
283
  }
284
284
 
285
+ // src/cdp-driver/selector-utils.ts
286
+ function queryJS(selector) {
287
+ if (selector.startsWith("xpath=")) {
288
+ const xpath = JSON.stringify(selector.slice(6));
289
+ return `document.evaluate(${xpath}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue`;
290
+ }
291
+ return `document.querySelector(${JSON.stringify(selector)})`;
292
+ }
293
+ function queryAllJS(selector) {
294
+ if (selector.startsWith("xpath=")) {
295
+ const xpath = JSON.stringify(selector.slice(6));
296
+ return `(() => { const it = document.evaluate(${xpath}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); const r=[]; for(let i=0;i<it.snapshotLength;i++) r.push(it.snapshotItem(i)); return r; })()`;
297
+ }
298
+ return `document.querySelectorAll(${JSON.stringify(selector)})`;
299
+ }
300
+
285
301
  // src/cdp-driver/actionability.ts
286
302
  async function waitForActionable(page, selector, opts = {}) {
287
303
  const timeout = opts.timeout ?? 3e4;
@@ -306,7 +322,7 @@ async function waitForActionable(page, selector, opts = {}) {
306
322
  async function checkActionable(page, selector) {
307
323
  const result = await page.evaluate(`
308
324
  (function() {
309
- const el = document.querySelector(${JSON.stringify(selector)});
325
+ const el = ${queryJS(selector)};
310
326
  if (!el) return { ok: false, reason: 'not_found' };
311
327
 
312
328
  // Check attached to DOM
@@ -349,7 +365,7 @@ async function checkActionable(page, selector) {
349
365
  async function scrollIntoView(page, selector) {
350
366
  await page.evaluate(`
351
367
  (function() {
352
- const el = document.querySelector(${JSON.stringify(selector)});
368
+ const el = ${queryJS(selector)};
353
369
  if (el) el.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });
354
370
  })()
355
371
  `);
@@ -363,13 +379,21 @@ var XBLocatorImpl = class _XBLocatorImpl {
363
379
  this.page = page;
364
380
  this.selector = selector;
365
381
  }
382
+ /** Resolve selector to a JS expression that finds a single element (CSS or xpath). */
383
+ _q(sel) {
384
+ return queryJS(sel);
385
+ }
386
+ /** Resolve selector to a JS expression that finds all matching elements (CSS or xpath). */
387
+ _qa(sel) {
388
+ return queryAllJS(sel);
389
+ }
366
390
  // ── Actions ─────────────────────────────────────────────────
367
391
  async click(opts = {}) {
368
392
  const { rect } = await waitForActionable(this.page, this.selector, opts);
369
393
  await scrollIntoView(this.page, this.selector);
370
394
  const updatedRect = await this.page.evaluate(`
371
395
  (function() {
372
- const el = document.querySelector(${JSON.stringify(this.selector)});
396
+ const el = ${this._q(this.selector)};
373
397
  if (!el) return null;
374
398
  const rect = el.getBoundingClientRect();
375
399
  return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
@@ -389,7 +413,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
389
413
  await scrollIntoView(this.page, this.selector);
390
414
  await this.page.evaluate(`
391
415
  (function() {
392
- const el = document.querySelector(${JSON.stringify(this.selector)});
416
+ const el = ${this._q(this.selector)};
393
417
  if (!el) throw new Error('Element not found: ${this.selector.replace(/'/g, "\\'")}');
394
418
  el.focus();
395
419
  el.value = '';
@@ -399,7 +423,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
399
423
  await this.page.keyboard.insertText(value);
400
424
  await this.page.evaluate(`
401
425
  (function() {
402
- const el = document.querySelector(${JSON.stringify(this.selector)});
426
+ const el = ${this._q(this.selector)};
403
427
  if (el) {
404
428
  el.dispatchEvent(new Event('input', { bubbles: true }));
405
429
  el.dispatchEvent(new Event('change', { bubbles: true }));
@@ -412,7 +436,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
412
436
  await scrollIntoView(this.page, this.selector);
413
437
  await this.page.evaluate(`
414
438
  (function() {
415
- const el = document.querySelector(${JSON.stringify(this.selector)});
439
+ const el = ${this._q(this.selector)};
416
440
  if (el) el.focus();
417
441
  })()
418
442
  `);
@@ -423,7 +447,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
423
447
  await scrollIntoView(this.page, this.selector);
424
448
  await this.page.evaluate(`
425
449
  (function() {
426
- const el = document.querySelector(${JSON.stringify(this.selector)});
450
+ const el = ${this._q(this.selector)};
427
451
  if (el) el.focus();
428
452
  })()
429
453
  `);
@@ -440,7 +464,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
440
464
  await scrollIntoView(this.page, this.selector);
441
465
  const rect = await this.page.evaluate(`
442
466
  (function() {
443
- const el = document.querySelector(${JSON.stringify(this.selector)});
467
+ const el = ${this._q(this.selector)};
444
468
  if (!el) return { x: 0, y: 0, width: 0, height: 0 };
445
469
  const r = el.getBoundingClientRect();
446
470
  return { x: r.x, y: r.y, width: r.width, height: r.height };
@@ -458,7 +482,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
458
482
  await waitForActionable(this.page, this.selector, { timeout: opts.timeout });
459
483
  const isChecked = await this.page.evaluate(`
460
484
  (function() {
461
- const el = document.querySelector(${JSON.stringify(this.selector)});
485
+ const el = ${this._q(this.selector)};
462
486
  return el?.checked === true;
463
487
  })()
464
488
  `);
@@ -470,7 +494,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
470
494
  await waitForActionable(this.page, this.selector, { timeout: opts.timeout });
471
495
  const isChecked = await this.page.evaluate(`
472
496
  (function() {
473
- const el = document.querySelector(${JSON.stringify(this.selector)});
497
+ const el = ${this._q(this.selector)};
474
498
  return el?.checked === true;
475
499
  })()
476
500
  `);
@@ -483,7 +507,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
483
507
  const values = Array.isArray(value) ? value : [value];
484
508
  const selected = await this.page.evaluate(`
485
509
  (function() {
486
- const el = document.querySelector(${JSON.stringify(this.selector)});
510
+ const el = ${this._q(this.selector)};
487
511
  if (!el || el.tagName !== 'SELECT') throw new Error('Not a select element');
488
512
 
489
513
  const values = ${JSON.stringify(values)};
@@ -511,10 +535,15 @@ var XBLocatorImpl = class _XBLocatorImpl {
511
535
  }
512
536
  async screenshot(opts = {}) {
513
537
  await waitForActionable(this.page, this.selector);
514
- const nodeId = await this.page.querySelector(this.selector);
515
- if (!nodeId) throw new Error(`Element not found: ${this.selector}`);
516
- const box = await this.page.getBoxModel(nodeId);
517
- if (!box) throw new Error("Element has no box");
538
+ const box = await this.page.evaluate(`
539
+ (function() {
540
+ const el = ${this._q(this.selector)};
541
+ if (!el) return null;
542
+ const r = el.getBoundingClientRect();
543
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
544
+ })()
545
+ `);
546
+ if (!box) throw new Error(`Element not found: ${this.selector}`);
518
547
  return this.page.screenshot({
519
548
  ...opts,
520
549
  clip: { x: box.x, y: box.y, width: box.width, height: box.height }
@@ -526,14 +555,14 @@ var XBLocatorImpl = class _XBLocatorImpl {
526
555
  }
527
556
  async count() {
528
557
  return this.page.evaluate(`
529
- document.querySelectorAll(${JSON.stringify(this.selector)}).length
558
+ ${this._qa(this.selector)}.length
530
559
  `);
531
560
  }
532
561
  async isVisible() {
533
562
  try {
534
563
  const result = await this.page.evaluate(`
535
564
  (function() {
536
- const el = document.querySelector(${JSON.stringify(this.selector)});
565
+ const el = ${this._q(this.selector)};
537
566
  if (!el) return false;
538
567
  if (!el.isConnected) return false;
539
568
  const style = window.getComputedStyle(el);
@@ -553,7 +582,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
553
582
  async isEnabled() {
554
583
  return this.page.evaluate(`
555
584
  (function() {
556
- const el = document.querySelector(${JSON.stringify(this.selector)});
585
+ const el = ${this._q(this.selector)};
557
586
  if (!el) return false;
558
587
  return !el.disabled;
559
588
  })()
@@ -563,15 +592,20 @@ var XBLocatorImpl = class _XBLocatorImpl {
563
592
  return !await this.isEnabled();
564
593
  }
565
594
  async boundingBox() {
566
- const nodeId = await this.page.querySelector(this.selector);
567
- if (!nodeId) return null;
568
- return this.page.getBoxModel(nodeId);
595
+ return this.page.evaluate(`
596
+ (function() {
597
+ const el = ${this._q(this.selector)};
598
+ if (!el) return null;
599
+ const r = el.getBoundingClientRect();
600
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
601
+ })()
602
+ `);
569
603
  }
570
604
  // ── Text/HTML ───────────────────────────────────────────────
571
605
  async textContent() {
572
606
  return this.page.evaluate(`
573
607
  (function() {
574
- const el = document.querySelector(${JSON.stringify(this.selector)});
608
+ const el = ${this._q(this.selector)};
575
609
  return el?.textContent ?? null;
576
610
  })()
577
611
  `);
@@ -579,7 +613,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
579
613
  async innerText() {
580
614
  return this.page.evaluate(`
581
615
  (function() {
582
- const el = document.querySelector(${JSON.stringify(this.selector)});
616
+ const el = ${this._q(this.selector)};
583
617
  if (!el) throw new Error('Element not found');
584
618
  return el.innerText;
585
619
  })()
@@ -588,7 +622,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
588
622
  async innerHTML() {
589
623
  return this.page.evaluate(`
590
624
  (function() {
591
- const el = document.querySelector(${JSON.stringify(this.selector)});
625
+ const el = ${this._q(this.selector)};
592
626
  if (!el) throw new Error('Element not found');
593
627
  return el.innerHTML;
594
628
  })()
@@ -597,7 +631,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
597
631
  async getAttribute(name) {
598
632
  return this.page.evaluate(`
599
633
  (function() {
600
- const el = document.querySelector(${JSON.stringify(this.selector)});
634
+ const el = ${this._q(this.selector)};
601
635
  return el?.getAttribute(${JSON.stringify(name)}) ?? null;
602
636
  })()
603
637
  `);
@@ -605,13 +639,17 @@ var XBLocatorImpl = class _XBLocatorImpl {
605
639
  // ── Evaluate ────────────────────────────────────────────────
606
640
  async evaluate(fn, ...args) {
607
641
  const fnBody = typeof fn === "function" ? fn.toString() : fn;
642
+ const sel = JSON.stringify(this.selector);
643
+ const xpathPrefix = this.selector.startsWith("xpath=") ? JSON.stringify(this.selector.slice(6)) : "null";
608
644
  return this.page.evaluate(
609
- `(function(sel, fnStr, ...evalArgs) {
610
- const el = document.querySelector(sel);
645
+ `(function(sel, xpathExpr, fnStr, ...evalArgs) {
646
+ const el = xpathExpr
647
+ ? document.evaluate(xpathExpr, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
648
+ : document.querySelector(sel);
611
649
  if (!el) throw new Error('No element found for selector: ' + sel);
612
650
  const fn = new Function('return ' + fnStr)();
613
651
  return fn(el, ...evalArgs);
614
- })(${JSON.stringify(this.selector)}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
652
+ })(${sel}, ${xpathPrefix}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
615
653
  );
616
654
  }
617
655
  async ariaSnapshot() {
@@ -638,7 +676,7 @@ var XBLocatorImpl = class _XBLocatorImpl {
638
676
  }
639
677
  async all() {
640
678
  const n = await this.page.evaluate(`
641
- document.querySelectorAll(${JSON.stringify(this.selector)}).length
679
+ ${this._qa(this.selector)}.length
642
680
  `);
643
681
  const locators = [];
644
682
  for (let i = 0; i < n; i++) {
@@ -649,16 +687,33 @@ var XBLocatorImpl = class _XBLocatorImpl {
649
687
  async focus() {
650
688
  await this.page.evaluate(`
651
689
  (function() {
652
- const el = document.querySelector(${JSON.stringify(this.selector)});
690
+ const el = ${this._q(this.selector)};
653
691
  if (el) el.focus();
654
692
  })()
655
693
  `);
656
694
  }
657
695
  };
658
696
  var FilteredLocator = class extends XBLocatorImpl {
697
+ index;
659
698
  constructor(page, selector, index) {
660
- const indexedSelector = index === -1 ? `${selector}:last-of-type` : `${selector}:nth-of-type(${index + 1})`;
699
+ const indexedSelector = selector.startsWith("xpath=") ? selector : index === -1 ? `${selector}:last-of-type` : `${selector}:nth-of-type(${index + 1})`;
661
700
  super(page, indexedSelector);
701
+ this.index = index;
702
+ this._rawSelector = selector;
703
+ }
704
+ /** Original selector before index filtering */
705
+ _rawSelector;
706
+ /** For xpath selectors, override _q to return the nth element from evaluate results */
707
+ _q(sel) {
708
+ if (!sel.startsWith("xpath=")) return super._q(sel);
709
+ const xpath = JSON.stringify(this._rawSelector.slice(6));
710
+ return `(() => { const it = document.evaluate(${xpath}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); return ${this.index === -1 ? "it.snapshotItem(it.snapshotLength - 1)" : `it.snapshotItem(${this.index})`}; })()`;
711
+ }
712
+ /** For xpath selectors, override _qa to return all matching elements from evaluate */
713
+ _qa(sel) {
714
+ if (!sel.startsWith("xpath=")) return super._qa(sel);
715
+ const xpath = JSON.stringify(this._rawSelector.slice(6));
716
+ return `(() => { const it = document.evaluate(${xpath}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); const r=[]; for(let i=0;i<it.snapshotLength;i++) r.push(it.snapshotItem(i)); return r; })()`;
662
717
  }
663
718
  };
664
719
  var VisibleFilteredLocator = class extends XBLocatorImpl {
@@ -666,7 +721,7 @@ var VisibleFilteredLocator = class extends XBLocatorImpl {
666
721
  const tag = `data-xb-vt-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
667
722
  const found = await this.page.evaluate(`
668
723
  (function() {
669
- const els = document.querySelectorAll(${JSON.stringify(this.selector)});
724
+ const els = ${this._qa(this.selector)};
670
725
  for (const el of els) {
671
726
  if (!el.isConnected) continue;
672
727
  const style = window.getComputedStyle(el);
@@ -684,7 +739,7 @@ var VisibleFilteredLocator = class extends XBLocatorImpl {
684
739
  return await fn(`[${tag}]`);
685
740
  } finally {
686
741
  await this.page.evaluate(`
687
- document.querySelectorAll(${JSON.stringify(`[${tag}]`)}).forEach(el => el.removeAttribute(${JSON.stringify(tag)}))
742
+ ${this._qa(`[${tag}]`)}.forEach(el => el.removeAttribute(${JSON.stringify(tag)}))
688
743
  `);
689
744
  }
690
745
  }
@@ -704,7 +759,7 @@ var VisibleFilteredLocator = class extends XBLocatorImpl {
704
759
  return this.page.evaluate(`
705
760
  (function() {
706
761
  let count = 0;
707
- const els = document.querySelectorAll(${JSON.stringify(this.selector)});
762
+ const els = ${this._qa(this.selector)};
708
763
  for (const el of els) {
709
764
  if (!el.isConnected) continue;
710
765
  const style = window.getComputedStyle(el);
@@ -721,7 +776,7 @@ var VisibleFilteredLocator = class extends XBLocatorImpl {
721
776
  try {
722
777
  const result = await this.page.evaluate(`
723
778
  (function() {
724
- const els = document.querySelectorAll(${JSON.stringify(this.selector)});
779
+ const els = ${this._qa(this.selector)};
725
780
  for (const el of els) {
726
781
  if (!el.isConnected) continue;
727
782
  const style = window.getComputedStyle(el);
@@ -1166,20 +1221,20 @@ var XBPageImpl = class _XBPageImpl {
1166
1221
  const deadline = Date.now() + timeout;
1167
1222
  while (Date.now() < deadline) {
1168
1223
  const exists = await this.evaluate(
1169
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); return !!el; })()`
1224
+ `(function() { const el = ${queryJS(selector)}; return !!el; })()`
1170
1225
  );
1171
1226
  if (state === "attached" && exists) return;
1172
1227
  if (state === "detached" && !exists) return;
1173
1228
  if (state === "visible" && exists) {
1174
1229
  const visible = await this.evaluate(
1175
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); if (!el) return false; const rect = el.getBoundingClientRect(); const style = window.getComputedStyle(el); return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none'; })()`
1230
+ `(function() { const el = ${queryJS(selector)}; if (!el) return false; const rect = el.getBoundingClientRect(); const style = window.getComputedStyle(el); return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none'; })()`
1176
1231
  );
1177
1232
  if (visible) return;
1178
1233
  }
1179
1234
  if (state === "hidden") {
1180
1235
  if (!exists) return;
1181
1236
  const visible = await this.evaluate(
1182
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); if (!el) return false; const rect = el.getBoundingClientRect(); const style = window.getComputedStyle(el); return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none'; })()`
1237
+ `(function() { const el = ${queryJS(selector)}; if (!el) return false; const rect = el.getBoundingClientRect(); const style = window.getComputedStyle(el); return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none'; })()`
1183
1238
  );
1184
1239
  if (!visible) return;
1185
1240
  }
@@ -1222,6 +1277,8 @@ Last error: ${lastError.message}` : "";
1222
1277
  // ── Evaluation ──────────────────────────────────────────────
1223
1278
  async evaluate(fn, ...args) {
1224
1279
  if (this._closed) throw new Error("Page is closed");
1280
+ this.conn.send("Page.handleJavaScriptDialog", { accept: false }, this.sessionId).catch(() => {
1281
+ });
1225
1282
  let expression;
1226
1283
  if (typeof fn === "string") {
1227
1284
  expression = fn;
@@ -1261,23 +1318,31 @@ Last error: ${lastError.message}` : "";
1261
1318
  }
1262
1319
  async $eval(selector, fn, ...args) {
1263
1320
  const fnBody = typeof fn === "function" ? fn.toString() : fn;
1321
+ const selJSON = JSON.stringify(selector);
1322
+ const xpathPrefix = selector.startsWith("xpath=") ? JSON.stringify(selector.slice(6)) : "null";
1264
1323
  return this.evaluate(
1265
- `(function(sel, fnStr, ...evalArgs) {
1266
- const el = document.querySelector(sel);
1324
+ `(function(sel, xpathExpr, fnStr, ...evalArgs) {
1325
+ const el = xpathExpr
1326
+ ? document.evaluate(xpathExpr, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
1327
+ : document.querySelector(sel);
1267
1328
  if (!el) throw new Error('No element found for selector: ' + sel);
1268
1329
  const fn = new Function('return ' + fnStr)();
1269
1330
  return fn(el, ...evalArgs);
1270
- })(${JSON.stringify(selector)}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
1331
+ })(${selJSON}, ${xpathPrefix}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
1271
1332
  );
1272
1333
  }
1273
1334
  async $$eval(selector, fn, ...args) {
1274
1335
  const fnBody = typeof fn === "function" ? fn.toString() : fn;
1336
+ const selJSON = JSON.stringify(selector);
1337
+ const xpathPrefix = selector.startsWith("xpath=") ? JSON.stringify(selector.slice(6)) : "null";
1275
1338
  return this.evaluate(
1276
- `(function(sel, fnStr, ...evalArgs) {
1277
- const els = Array.from(document.querySelectorAll(sel));
1339
+ `(function(sel, xpathExpr, fnStr, ...evalArgs) {
1340
+ const els = xpathExpr
1341
+ ? (() => { const it = document.evaluate(xpathExpr, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); const r=[]; for(let i=0;i<it.snapshotLength;i++) r.push(it.snapshotItem(i)); return r; })()
1342
+ : Array.from(document.querySelectorAll(sel));
1278
1343
  const fn = new Function('return ' + fnStr)();
1279
1344
  return fn(els, ...evalArgs);
1280
- })(${JSON.stringify(selector)}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
1345
+ })(${selJSON}, ${xpathPrefix}, ${JSON.stringify(fnBody)}${args.length > 0 ? ", " + args.map((a) => JSON.stringify(a)).join(", ") : ""})`
1281
1346
  );
1282
1347
  }
1283
1348
  // ── Locator ─────────────────────────────────────────────────
@@ -1350,22 +1415,22 @@ Last error: ${lastError.message}` : "";
1350
1415
  // ── Convenience selectors ───────────────────────────────────
1351
1416
  async textContent(selector) {
1352
1417
  return this.evaluate(
1353
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); return el?.textContent ?? null; })()`
1418
+ `(function() { const el = ${queryJS(selector)}; return el?.textContent ?? null; })()`
1354
1419
  );
1355
1420
  }
1356
1421
  async innerText(selector) {
1357
1422
  return this.evaluate(
1358
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); if (!el) throw new Error('Element not found'); return el.innerText; })()`
1423
+ `(function() { const el = ${queryJS(selector)}; if (!el) throw new Error('Element not found'); return el.innerText; })()`
1359
1424
  );
1360
1425
  }
1361
1426
  async innerHTML(selector) {
1362
1427
  return this.evaluate(
1363
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); if (!el) throw new Error('Element not found'); return el.innerHTML; })()`
1428
+ `(function() { const el = ${queryJS(selector)}; if (!el) throw new Error('Element not found'); return el.innerHTML; })()`
1364
1429
  );
1365
1430
  }
1366
1431
  async getAttribute(selector, name) {
1367
1432
  return this.evaluate(
1368
- `(function() { const el = document.querySelector(${JSON.stringify(selector)}); return el?.getAttribute(${JSON.stringify(name)}) ?? null; })()`
1433
+ `(function() { const el = ${queryJS(selector)}; return el?.getAttribute(${JSON.stringify(name)}) ?? null; })()`
1369
1434
  );
1370
1435
  }
1371
1436
  // ── Query ───────────────────────────────────────────────────
@@ -1671,7 +1736,7 @@ Last error: ${lastError.message}` : "";
1671
1736
  setTimeout(() => {
1672
1737
  this.conn.send("Page.handleJavaScriptDialog", { accept: false }, this.sessionId).catch(() => {
1673
1738
  });
1674
- }, 100);
1739
+ }, 0);
1675
1740
  })
1676
1741
  );
1677
1742
  this._subscriptions.push(
@@ -1986,7 +2051,7 @@ Last error: ${lastError.message}` : "";
1986
2051
  await this.evaluate(`
1987
2052
  (function() {
1988
2053
  var selector = ${JSON.stringify(selector)};
1989
- var input = document.querySelector(selector);
2054
+ var input = ${queryJS(selector)};
1990
2055
  if (!input) throw new Error('Element not found: ' + selector);
1991
2056
 
1992
2057
  var fileList = ${JSON.stringify(fileList)};
@@ -2011,7 +2076,7 @@ Last error: ${lastError.message}` : "";
2011
2076
  async dragAndDrop(source, target) {
2012
2077
  const sourceRect = await this.evaluate(`
2013
2078
  (function() {
2014
- const el = document.querySelector(${JSON.stringify(source)});
2079
+ const el = ${queryJS(source)};
2015
2080
  if (!el) throw new Error('Source not found: ${source}');
2016
2081
  el.scrollIntoView({ behavior: 'instant', block: 'center' });
2017
2082
  const r = el.getBoundingClientRect();
@@ -2020,7 +2085,7 @@ Last error: ${lastError.message}` : "";
2020
2085
  `);
2021
2086
  const targetRect = await this.evaluate(`
2022
2087
  (function() {
2023
- const el = document.querySelector(${JSON.stringify(target)});
2088
+ const el = ${queryJS(target)};
2024
2089
  if (!el) throw new Error('Target not found: ${target}');
2025
2090
  el.scrollIntoView({ behavior: 'instant', block: 'center' });
2026
2091
  const r = el.getBoundingClientRect();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  launch
3
- } from "./chunk-E5WWMKXB.js";
3
+ } from "./chunk-QFROODUU.js";
4
4
  import {
5
5
  errMsg
6
6
  } from "./chunk-GDKLH7ZY.js";