@enekesabel/playwright-lite 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +87 -87
  2. package/dist/index.mjs +328 -145
  3. package/package.json +4 -4
package/dist/index.mjs CHANGED
@@ -14754,6 +14754,27 @@ function validateString(value, name) {
14754
14754
  if (typeof value === "string") return value;
14755
14755
  throw new Error(`${name}: expected string, got ${typeof value}`);
14756
14756
  }
14757
+ /**
14758
+ * `delay` is `float?` in the pinned protocol for press, type and the pointer
14759
+ * actions. Like the pointer options, a non-finite value is rejected instead of
14760
+ * reaching the input path as NaN, and a boxed `Number` is unwrapped for the
14761
+ * caller to forward instead of leaking an object into the input path.
14762
+ */
14763
+ function validateDelay(value) {
14764
+ if (value === void 0) return void 0;
14765
+ const delay = value instanceof Number ? value.valueOf() : value;
14766
+ if (typeof delay !== "number" || !Number.isFinite(delay)) throw new TypeError("delay: expected number");
14767
+ return delay;
14768
+ }
14769
+ /**
14770
+ * `signal` is a client-side option in the pinned API: it never reaches the
14771
+ * protocol, so the adapter checks the value itself. `name` is the API member
14772
+ * or option group the message speaks for, such as `click` or `Query`.
14773
+ */
14774
+ function validateSignal(name, value) {
14775
+ if (value === void 0 || value instanceof AbortSignal) return;
14776
+ throw new TypeError(`${name} signal must be an AbortSignal`);
14777
+ }
14757
14778
  function validateNoWaitAfter(method, value) {
14758
14779
  if (method !== "click" && method !== "press") return;
14759
14780
  if (value === void 0 || typeof value === "boolean" || value instanceof Boolean) return;
@@ -15571,16 +15592,16 @@ var LocatorImpl = class LocatorImpl {
15571
15592
  return this.ownerPage.resolveAll(this.selector).map((element) => this.ownerPage.elementHandleFor(element));
15572
15593
  }
15573
15594
  async getAttribute(name, options) {
15574
- return this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options);
15595
+ return withAbortPrefix("locator.getAttribute", () => this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options));
15575
15596
  }
15576
15597
  async textContent(options) {
15577
- return this.ownerPage.locatorTextContent(this.selector, this.label, options);
15598
+ return withAbortPrefix("locator.textContent", () => this.ownerPage.locatorTextContent(this.selector, this.label, options));
15578
15599
  }
15579
15600
  async innerText(options) {
15580
- return this.ownerPage.locatorInnerText(this.selector, this.label, options);
15601
+ return withAbortPrefix("locator.innerText", () => this.ownerPage.locatorInnerText(this.selector, this.label, options));
15581
15602
  }
15582
15603
  async innerHTML(options) {
15583
- return this.ownerPage.locatorInnerHTML(this.selector, this.label, options);
15604
+ return withAbortPrefix("locator.innerHTML", () => this.ownerPage.locatorInnerHTML(this.selector, this.label, options));
15584
15605
  }
15585
15606
  async allInnerTexts() {
15586
15607
  return this.ownerPage.locatorAllInnerTexts(this.selector);
@@ -15589,19 +15610,19 @@ var LocatorImpl = class LocatorImpl {
15589
15610
  return this.ownerPage.locatorAllTextContents(this.selector);
15590
15611
  }
15591
15612
  async inputValue(options) {
15592
- return this.ownerPage.locatorInputValue(this.selector, this.label, options);
15613
+ return withAbortPrefix("locator.inputValue", () => this.ownerPage.locatorInputValue(this.selector, this.label, options));
15593
15614
  }
15594
15615
  async isEnabled(options) {
15595
- return this.ownerPage.locatorIsEnabled(this.selector, this.label, options);
15616
+ return withAbortPrefix("locator.isEnabled", () => this.ownerPage.locatorIsEnabled(this.selector, this.label, options));
15596
15617
  }
15597
15618
  async isDisabled(options) {
15598
- return this.ownerPage.locatorIsDisabled(this.selector, this.label, options);
15619
+ return withAbortPrefix("locator.isDisabled", () => this.ownerPage.locatorIsDisabled(this.selector, this.label, options));
15599
15620
  }
15600
15621
  async isChecked(options) {
15601
- return this.ownerPage.locatorIsChecked(this.selector, this.label, options);
15622
+ return withAbortPrefix("locator.isChecked", () => this.ownerPage.locatorIsChecked(this.selector, this.label, options));
15602
15623
  }
15603
15624
  async isEditable(options) {
15604
- return this.ownerPage.locatorIsEditable(this.selector, this.label, options);
15625
+ return withAbortPrefix("locator.isEditable", () => this.ownerPage.locatorIsEditable(this.selector, this.label, options));
15605
15626
  }
15606
15627
  async isVisible(options) {
15607
15628
  return this.ownerPage.locatorIsVisible(this.selector, this.label, options);
@@ -15610,7 +15631,7 @@ var LocatorImpl = class LocatorImpl {
15610
15631
  return !this.ownerPage.locatorIsVisible(this.selector, this.label, options);
15611
15632
  }
15612
15633
  async boundingBox(options) {
15613
- return this.ownerPage.locatorBoundingBox(this.selector, this.label, options);
15634
+ return withAbortPrefix("locator.boundingBox", () => this.ownerPage.locatorBoundingBox(this.selector, this.label, options));
15614
15635
  }
15615
15636
  /**
15616
15637
  * Captures the accessibility snapshot rooted at this locator's sole element.
@@ -15620,7 +15641,7 @@ var LocatorImpl = class LocatorImpl {
15620
15641
  * not add frame traversal or browser-process behavior.
15621
15642
  */
15622
15643
  async ariaSnapshot(options = {}) {
15623
- return this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options);
15644
+ return withAbortPrefix("locator.ariaSnapshot", () => this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options));
15624
15645
  }
15625
15646
  /**
15626
15647
  * The public Playwright matcher implementation calls this private-shaped
@@ -15641,7 +15662,7 @@ var LocatorImpl = class LocatorImpl {
15641
15662
  }
15642
15663
  async evaluate(pageFunction, arg, options) {
15643
15664
  assertMaxArguments(arguments.length, 3);
15644
- return this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options);
15665
+ return withAbortPrefix("locator.evaluate", () => this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options));
15645
15666
  }
15646
15667
  async evaluateAll(pageFunction, arg) {
15647
15668
  assertMaxArguments(arguments.length, 2);
@@ -15654,26 +15675,45 @@ var LocatorImpl = class LocatorImpl {
15654
15675
  });
15655
15676
  }
15656
15677
  async fill(value, options) {
15657
- rejectUnsupportedOptions("fill", options, ["noWaitAfter", "timeout"]);
15658
- await this.ownerPage.fillSelector(this.selector, value, this.label, options?.timeout);
15678
+ rejectUnsupportedOptions("fill", options, [
15679
+ "noWaitAfter",
15680
+ "signal",
15681
+ "timeout"
15682
+ ]);
15683
+ await withAbortPrefix("locator.fill", () => this.ownerPage.fillSelector(this.selector, value, this.label, options?.timeout, void 0, true, options?.signal));
15659
15684
  }
15660
15685
  async setInputFiles(files, options) {
15661
- rejectUnsupportedOptions("setInputFiles", options, ["noWaitAfter", "timeout"]);
15662
- await this.ownerPage.setInputFilesSelector(this.selector, files, options, true);
15686
+ rejectUnsupportedOptions("setInputFiles", options, [
15687
+ "noWaitAfter",
15688
+ "signal",
15689
+ "timeout"
15690
+ ]);
15691
+ await withAbortPrefix("locator.setInputFiles", () => this.ownerPage.setInputFilesSelector(this.selector, files, options, true));
15663
15692
  }
15664
15693
  async press(key, options) {
15665
- rejectUnsupportedOptions("press", options, ["noWaitAfter", "timeout"]);
15666
- await this.ownerPage.pressSelector(this.selector, key, this.label, options?.timeout);
15694
+ const delay = rejectUnsupportedOptions("press", options, [
15695
+ "delay",
15696
+ "noWaitAfter",
15697
+ "signal",
15698
+ "timeout"
15699
+ ]);
15700
+ await withAbortPrefix("locator.press", () => this.ownerPage.pressSelector(this.selector, key, this.label, options?.timeout, void 0, true, options?.signal, delay));
15667
15701
  }
15668
15702
  async focus(options) {
15669
- await this.ownerPage.focusSelector(this.selector, this.label, options);
15703
+ rejectUnsupportedOptions("focus", options, ["signal", "timeout"]);
15704
+ await withAbortPrefix("locator.focus", () => this.ownerPage.focusSelector(this.selector, this.label, options));
15670
15705
  }
15671
15706
  async blur(options) {
15672
- await this.ownerPage.blurSelector(this.selector, this.label, options);
15707
+ rejectUnsupportedOptions("blur", options, ["signal", "timeout"]);
15708
+ await withAbortPrefix("locator.blur", () => this.ownerPage.blurSelector(this.selector, this.label, options));
15673
15709
  }
15674
15710
  async clear(options) {
15675
- rejectUnsupportedOptions("clear", options, ["noWaitAfter", "timeout"]);
15676
- await this.ownerPage.fillSelector(this.selector, "", this.label, options?.timeout);
15711
+ rejectUnsupportedOptions("clear", options, [
15712
+ "noWaitAfter",
15713
+ "signal",
15714
+ "timeout"
15715
+ ]);
15716
+ await withAbortPrefix("locator.clear", () => this.ownerPage.fillSelector(this.selector, "", this.label, options?.timeout, void 0, true, options?.signal));
15677
15717
  }
15678
15718
  async hover(options) {
15679
15719
  await this.ownerPage.hoverSelector(this.selector, this.label, options?.timeout, void 0, {
@@ -15706,39 +15746,52 @@ var LocatorImpl = class LocatorImpl {
15706
15746
  });
15707
15747
  }
15708
15748
  async dispatchEvent(type, eventInit = {}, options) {
15709
- rejectUnsupportedOptions("dispatchEvent", options, ["timeout"]);
15710
- await this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout);
15749
+ rejectUnsupportedOptions("dispatchEvent", options, ["signal", "timeout"]);
15750
+ await withAbortPrefix("locator.dispatchEvent", () => this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout, void 0, true, options?.signal));
15711
15751
  }
15712
15752
  async selectOption(values, options) {
15713
- rejectUnsupportedOptions("selectOption", options, ["noWaitAfter", "timeout"]);
15714
- return this.ownerPage.selectOptionSelector(this.selector, values, this.label, options?.timeout);
15753
+ rejectUnsupportedOptions("selectOption", options, [
15754
+ "noWaitAfter",
15755
+ "signal",
15756
+ "timeout"
15757
+ ]);
15758
+ return withAbortPrefix("locator.selectOption", () => this.ownerPage.selectOptionSelector(this.selector, values, this.label, options?.timeout, void 0, true, options?.signal));
15715
15759
  }
15716
15760
  async selectText(options) {
15717
- rejectUnsupportedOptions("selectText", options, ["timeout"]);
15718
- await this.ownerPage.selectText(this.selector, this.label, options?.timeout);
15761
+ rejectUnsupportedOptions("selectText", options, ["signal", "timeout"]);
15762
+ await withAbortPrefix("locator.selectText", () => this.ownerPage.selectText(this.selector, this.label, options?.timeout, void 0, options?.signal));
15719
15763
  }
15720
15764
  async scrollIntoViewIfNeeded(options) {
15721
- rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["timeout"]);
15722
- await this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout);
15765
+ rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["signal", "timeout"]);
15766
+ await withAbortPrefix("locator.scrollIntoViewIfNeeded", () => this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout, void 0, options?.signal));
15723
15767
  }
15724
15768
  async type(text, options = {}) {
15769
+ await withAbortPrefix("locator.type", () => this.typeText(text, options));
15770
+ }
15771
+ async pressSequentially(text, options = {}) {
15772
+ await withAbortPrefix("locator.pressSequentially", () => this.typeText(text, options));
15773
+ }
15774
+ async typeText(text, options) {
15725
15775
  rejectUnsupportedOptions("type", options, [
15726
15776
  "delay",
15727
15777
  "noWaitAfter",
15778
+ "signal",
15728
15779
  "timeout"
15729
15780
  ]);
15730
- await this.ownerPage.type(this.selector, text, options, this.label);
15731
- }
15732
- async pressSequentially(text, options = {}) {
15733
- await this.type(text, options);
15781
+ await this.ownerPage.typeSelector(this.selector, text, options, this.label, true);
15734
15782
  }
15735
15783
  async waitFor(options = {}) {
15736
15784
  const state = options.state ?? "visible";
15737
- rejectUnsupportedOptions("waitFor", options, ["state", "timeout"]);
15738
- await this.ownerPage.waitForState(this.selector, {
15785
+ rejectUnsupportedOptions("waitFor", options, [
15786
+ "signal",
15787
+ "state",
15788
+ "timeout"
15789
+ ]);
15790
+ await withAbortPrefix("locator.waitFor", () => this.ownerPage.waitForState(this.selector, {
15791
+ signal: options.signal,
15739
15792
  state,
15740
15793
  timeout: options.timeout
15741
- }, this.label);
15794
+ }, this.label));
15742
15795
  }
15743
15796
  };
15744
15797
  /**
@@ -15752,11 +15805,14 @@ function requireBrand(value, context) {
15752
15805
  if (typeof payload !== "object" || payload === null || typeof payload.getSelector !== "function" || typeof payload.resolveElements !== "function") throw new TypeError(`${context}: expected an PlaywrightLite Locator, got incompatible branded object`);
15753
15806
  return payload;
15754
15807
  }
15808
+ /** Returns the normalized `delay`, unwrapped like the pointer options. */
15755
15809
  function rejectUnsupportedOptions(method, options, supported = []) {
15756
- if (!options) return;
15810
+ if (!options) return void 0;
15757
15811
  const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && !supported.includes(key));
15758
15812
  if (unsupported.length > 0) throw new Error(`${method}(): unsupported Playwright option(s): ${unsupported.join(", ")}.`);
15813
+ validateSignal(method, options.signal);
15759
15814
  if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
15815
+ return supported.includes("delay") ? validateDelay(options.delay) : void 0;
15760
15816
  }
15761
15817
  function cssObjectToString(style) {
15762
15818
  return Object.entries(style).map(([key, value]) => {
@@ -15880,22 +15936,22 @@ var PageImpl = class PageImpl {
15880
15936
  this.injected.hideHighlight();
15881
15937
  }
15882
15938
  async getAttribute(selector, name, options) {
15883
- return this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name));
15939
+ return withAbortPrefix("page.getAttribute", () => this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name)));
15884
15940
  }
15885
15941
  async textContent(selector, options) {
15886
- return this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent);
15942
+ return withAbortPrefix("page.textContent", () => this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent));
15887
15943
  }
15888
15944
  async inputValue(selector, options) {
15889
- return this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element));
15945
+ return withAbortPrefix("page.inputValue", () => this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element)));
15890
15946
  }
15891
15947
  async isEnabled(selector, options) {
15892
- return this.queryState(selector, "enabled", options, false);
15948
+ return withAbortPrefix("page.isEnabled", () => this.queryState(selector, "enabled", options, false));
15893
15949
  }
15894
15950
  async isDisabled(selector, options) {
15895
- return this.queryState(selector, "disabled", options, false);
15951
+ return withAbortPrefix("page.isDisabled", () => this.queryState(selector, "disabled", options, false));
15896
15952
  }
15897
15953
  async isChecked(selector, options) {
15898
- return this.queryState(selector, "checked", options, false);
15954
+ return withAbortPrefix("page.isChecked", () => this.queryState(selector, "checked", options, false));
15899
15955
  }
15900
15956
  async $(selector, options = {}) {
15901
15957
  assertDollarOptions(options);
@@ -15905,7 +15961,7 @@ var PageImpl = class PageImpl {
15905
15961
  return this.resolveAll(selector).map((element) => this.elementHandleFor(element));
15906
15962
  }
15907
15963
  async waitForSelector(selector, options = {}) {
15908
- return await this.waitForSelectorInRoot(this.document, selector, options);
15964
+ return await withAbortPrefix("page.waitForSelector", () => this.waitForSelectorInRoot(this.document, selector, options));
15909
15965
  }
15910
15966
  async waitForSelectorWithinElement(root, selector, options = {}) {
15911
15967
  return await this.waitForSelectorInRoot(root, selector, options, false);
@@ -15950,7 +16006,7 @@ var PageImpl = class PageImpl {
15950
16006
  const isArray = expression === "to.have.count" || expression.endsWith(".array");
15951
16007
  const elements = this.resolveAll(selector);
15952
16008
  if (!elements.length) return missingExpectationAttempt(expression, expectOptions);
15953
- if (!isArray && elements.length > 1) throw new Error(`strict mode violation: locator ${JSON.stringify(selector)} resolved to ${elements.length} elements`);
16009
+ if (!isArray && elements.length > 1) throw presentOriginalXPath(this.injected.strictModeViolationError(this.injected.parseSelector(selector), elements), selector);
15954
16010
  const injectedOptions = Object.fromEntries(Object.entries(options).filter(([key]) => key !== "timeout" && key !== "signal"));
15955
16011
  if (expression === "to.match.aria" && typeof injectedOptions.expectedValue === "string") injectedOptions.expectedValue = parseAriaExpectation(injectedOptions.expectedValue);
15956
16012
  const result = await this.injected.expect(elements[0], {
@@ -15976,6 +16032,7 @@ var PageImpl = class PageImpl {
15976
16032
  */
15977
16033
  async performPointerAction(selector, label, action, options, deadline, checked, apiMethod = action) {
15978
16034
  try {
16035
+ this.attachActionSignal(deadline, options.signal);
15979
16036
  while (true) {
15980
16037
  this.assertActionDeadline(deadline, action);
15981
16038
  try {
@@ -16035,12 +16092,13 @@ var PageImpl = class PageImpl {
16035
16092
  if (!checked && "isRadio" in state && state.isRadio) throw new Error("Cannot uncheck radio button. Radio buttons can only be unchecked by selecting another radio button in the same group.");
16036
16093
  return state.matches === checked;
16037
16094
  }
16038
- async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout)) {
16095
+ async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16096
+ this.attachActionSignal(deadline, signal);
16039
16097
  const { element } = await this.retryActionability(selector, label, "fill", [
16040
16098
  "visible",
16041
16099
  "enabled",
16042
16100
  "editable"
16043
- ], false, deadline);
16101
+ ], false, deadline, void 0, void 0, strict);
16044
16102
  this.assertActionDeadline(deadline, "fill");
16045
16103
  const result = this.actionableInjected.fill(element, value);
16046
16104
  if (result === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
@@ -16050,14 +16108,18 @@ var PageImpl = class PageImpl {
16050
16108
  if (!inputTarget) throw new Error(`Element is not connected for locator ${label}`);
16051
16109
  this.insertFilledText(inputTarget, value, deadline, "fill");
16052
16110
  }
16053
- async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout)) {
16054
- const element = await this.query(selector, label, { timeout }, true, (candidate) => candidate, deadline);
16111
+ async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal, delay) {
16112
+ this.attachActionSignal(deadline, signal);
16113
+ const element = await this.query(selector, label, {
16114
+ signal,
16115
+ timeout
16116
+ }, strict, (candidate) => candidate, deadline);
16055
16117
  this.assertActionDeadline(deadline, "press");
16056
16118
  this.focusElement(element);
16057
- await this.keyboard.press(key, {}, deadline);
16119
+ await this.keyboard.press(key, { delay }, deadline);
16058
16120
  }
16059
- async focusSelector(selector, label, options) {
16060
- await this.query(selector, label, options, true, (element) => {
16121
+ async focusSelector(selector, label, options, strict = true) {
16122
+ await this.query(selector, label, options, strict, (element) => {
16061
16123
  if (this.actionableInjected.focusNode(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
16062
16124
  });
16063
16125
  }
@@ -16075,27 +16137,35 @@ var PageImpl = class PageImpl {
16075
16137
  if (typeof checked !== "boolean") throw new TypeError("checked must be a boolean");
16076
16138
  await this.performPointerAction(selector, label, "click", options, deadline, checked, apiMethod);
16077
16139
  }
16078
- async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout)) {
16140
+ async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16141
+ this.attachActionSignal(deadline, signal);
16079
16142
  const options = (values === null ? [] : Array.isArray(values) ? values : [values]).map((value) => typeof value === "string" ? { valueOrLabel: value } : value);
16080
16143
  let lastError;
16081
16144
  while (true) {
16082
16145
  if (Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded.${lastError ? ` ${lastError.message}` : ""}`, { cause: lastError });
16083
- const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline);
16146
+ const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline, void 0, void 0, strict);
16084
16147
  this.assertActionDeadline(deadline, "select option");
16085
16148
  const result = this.actionableInjected.selectOptions(element, options);
16086
16149
  if (Array.isArray(result)) return result;
16087
16150
  lastError = result === "error:optionnotenabled" ? /* @__PURE__ */ new Error("Element is not enabled") : result === "error:notconnected" ? /* @__PURE__ */ new Error(`Element is not connected for locator ${label}`) : /* @__PURE__ */ new Error("Options not found");
16088
16151
  const remaining = deadline.expiresAt - Date.now();
16089
16152
  if (remaining <= 0) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
16090
- await this.wait(Math.min(ACTION_RETRY_DELAY, remaining));
16153
+ try {
16154
+ await this.waitWithinActionDeadline(Math.min(ACTION_RETRY_DELAY, remaining), deadline, "select option");
16155
+ } catch (error) {
16156
+ if (error instanceof AdapterTimeoutError) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
16157
+ throw error;
16158
+ }
16091
16159
  }
16092
16160
  }
16093
- async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
16161
+ async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
16162
+ this.attachActionSignal(deadline, signal);
16094
16163
  const { element } = await this.retryActionability(selector, label, "select text", ["visible"], false, deadline);
16095
16164
  this.assertActionDeadline(deadline, "select text");
16096
16165
  if (this.actionableInjected.selectText(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
16097
16166
  }
16098
- async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
16167
+ async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
16168
+ this.attachActionSignal(deadline, signal);
16099
16169
  const { element } = await this.retryActionability(selector, label, "scroll into view", ["stable"], false, deadline);
16100
16170
  this.assertActionDeadline(deadline, "scroll into view");
16101
16171
  this.scrollIntoViewIfNeeded(element);
@@ -16105,6 +16175,7 @@ var PageImpl = class PageImpl {
16105
16175
  try {
16106
16176
  await this.waitForSelectorInRoot(this.document, selector, {
16107
16177
  state: options.state,
16178
+ signal: options.signal,
16108
16179
  strict: true,
16109
16180
  timeout: options.timeout
16110
16181
  });
@@ -16118,7 +16189,11 @@ var PageImpl = class PageImpl {
16118
16189
  if (options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError("setInputFiles strict must be a boolean");
16119
16190
  const payloads = inputFilePayloads(files);
16120
16191
  const deadline = this.createActionDeadline(options.timeout);
16121
- await this.query(selector, selector, { timeout: options.timeout }, strict || options.strict === true, (element) => {
16192
+ this.attachActionSignal(deadline, options.signal);
16193
+ await this.query(selector, selector, {
16194
+ signal: options.signal,
16195
+ timeout: options.timeout
16196
+ }, strict || options.strict === true, (element) => {
16122
16197
  this.assertActionDeadline(deadline, "setInputFiles");
16123
16198
  const input = this.injected.retarget(element, "follow-label");
16124
16199
  if (!input || !input.isConnected) throw new Error("Element is not connected");
@@ -16161,28 +16236,30 @@ var PageImpl = class PageImpl {
16161
16236
  this.defaultNavigationTimeout = validateTimeout(timeout, "Default navigation timeout");
16162
16237
  }
16163
16238
  async innerText(selector, options) {
16164
- return this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
16239
+ return withAbortPrefix("page.innerText", () => this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
16165
16240
  if (element.namespaceURI !== "http://www.w3.org/1999/xhtml") throw new Error("Node is not an HTMLElement");
16166
16241
  return element.innerText;
16167
- });
16242
+ }));
16168
16243
  }
16169
16244
  async innerHTML(selector, options) {
16170
- return this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML);
16245
+ return withAbortPrefix("page.innerHTML", () => this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML));
16171
16246
  }
16172
16247
  async isEditable(selector, options) {
16173
- return this.queryState(selector, "editable", options, false);
16248
+ return withAbortPrefix("page.isEditable", () => this.queryState(selector, "editable", options, false));
16174
16249
  }
16175
16250
  async isVisible(selector, options) {
16176
- assertQueryOptions(options, true);
16177
- this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16178
- if (options?.signal?.aborted) throw queryAborted(options.signal);
16251
+ return this.selectorIsVisible("isVisible", selector, options);
16252
+ }
16253
+ async isHidden(selector, options) {
16254
+ return !this.selectorIsVisible("isHidden", selector, options);
16255
+ }
16256
+ selectorIsVisible(method, selector, options) {
16257
+ assertQueryOptions(options, ["strict", "timeout"]);
16258
+ if (options?.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
16179
16259
  const element = options?.strict ? this.resolveLocatorElement(selector, true) : this.resolveAll(selector)[0];
16180
16260
  if (!element) return false;
16181
16261
  return this.elementState(element, "visible").matches;
16182
16262
  }
16183
- async isHidden(selector, options) {
16184
- return !await this.isVisible(selector, options);
16185
- }
16186
16263
  async click(selector, options) {
16187
16264
  assertPointerActionOptions("click", options);
16188
16265
  await this.clickSelector(selector, `page.click(${JSON.stringify(selector)})`, options?.timeout, void 0, {
@@ -16191,28 +16268,45 @@ var PageImpl = class PageImpl {
16191
16268
  });
16192
16269
  }
16193
16270
  async fill(selector, value, options) {
16194
- assertPageActionOptions("fill", options, ["noWaitAfter"]);
16195
- await this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout);
16271
+ assertPageActionOptions("fill", options, ["noWaitAfter", "strict"]);
16272
+ await withAbortPrefix("page.fill", () => this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16196
16273
  }
16197
16274
  async setInputFiles(selector, files, options) {
16198
- await this.setInputFilesSelector(selector, files, options);
16275
+ await withAbortPrefix("page.setInputFiles", () => this.setInputFilesSelector(selector, files, options));
16199
16276
  }
16200
16277
  async press(selector, key, options) {
16201
- assertPageActionOptions("press", options, ["noWaitAfter"]);
16202
- await this.pressSelector(selector, key, `page.press(${JSON.stringify(selector)})`, options?.timeout);
16278
+ const delay = assertPageActionOptions("press", options, [
16279
+ "delay",
16280
+ "noWaitAfter",
16281
+ "strict"
16282
+ ]);
16283
+ await withAbortPrefix("page.press", () => this.pressSelector(selector, key, `page.press(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal, delay));
16284
+ }
16285
+ async type(selector, text, options) {
16286
+ await withAbortPrefix("page.type", () => this.typeSelector(selector, text, options, `page.type(${JSON.stringify(selector)})`, options?.strict === true));
16203
16287
  }
16204
- async type(selector, text, options, label = `page.type(${JSON.stringify(selector)})`) {
16205
- assertPageActionOptions("type", options, ["delay", "noWaitAfter"]);
16288
+ async typeSelector(selector, text, options, label, strict) {
16289
+ const delay = assertPageActionOptions("type", options, [
16290
+ "delay",
16291
+ "noWaitAfter",
16292
+ "strict"
16293
+ ]);
16206
16294
  const deadline = this.createActionDeadline(options?.timeout);
16207
- for (const character of text) {
16208
- if (keyboardLayout.has(character)) await this.pressSelector(selector, character, label, options?.timeout, deadline);
16209
- else await this.insertTextSelector(selector, character, label, deadline);
16210
- if (options?.delay && options.delay > 0) await this.waitWithinActionDeadline(options.delay, deadline, "press");
16211
- }
16295
+ this.attachActionSignal(deadline, options?.signal);
16296
+ await this.query(selector, label, {
16297
+ signal: options?.signal,
16298
+ timeout: options?.timeout
16299
+ }, strict, (element) => {
16300
+ if (this.actionableInjected.focusNode(element, true) === "error:notconnected") throw new Error("Element is not connected");
16301
+ }, deadline);
16302
+ await this.keyboard.type(text, { delay }, deadline);
16212
16303
  }
16213
16304
  async focus(selector, options) {
16214
- assertPageActionOptions("focus", options);
16215
- await this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`, options);
16305
+ assertPageActionOptions("focus", options, ["strict"]);
16306
+ await withAbortPrefix("page.focus", () => this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`, {
16307
+ signal: options?.signal,
16308
+ timeout: options?.timeout
16309
+ }, options?.strict === true));
16216
16310
  }
16217
16311
  async hover(selector, options) {
16218
16312
  await this.hoverSelector(selector, `page.hover(${JSON.stringify(selector)})`, options?.timeout, void 0, {
@@ -16221,8 +16315,8 @@ var PageImpl = class PageImpl {
16221
16315
  });
16222
16316
  }
16223
16317
  async selectOption(selector, values, options) {
16224
- assertPageActionOptions("selectOption", options, ["noWaitAfter"]);
16225
- return this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout);
16318
+ assertPageActionOptions("selectOption", options, ["noWaitAfter", "strict"]);
16319
+ return withAbortPrefix("page.selectOption", () => this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16226
16320
  }
16227
16321
  async check(selector, options) {
16228
16322
  await this.setCheckedSelector(selector, true, `page.check(${JSON.stringify(selector)})`, {
@@ -16250,10 +16344,14 @@ var PageImpl = class PageImpl {
16250
16344
  }
16251
16345
  async dispatchEvent(selector, type, eventInit = {}, options) {
16252
16346
  assertPageDispatchEventOptions(options);
16253
- await this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true);
16347
+ await withAbortPrefix("page.dispatchEvent", () => this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16254
16348
  }
16255
- async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true) {
16256
- await this.query(selector, label, { timeout }, strict, (element) => this.actionableInjected.dispatchEvent(element, type, eventInit), deadline);
16349
+ async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16350
+ this.attachActionSignal(deadline, signal);
16351
+ await this.query(selector, label, {
16352
+ signal,
16353
+ timeout
16354
+ }, strict, (element) => this.actionableInjected.dispatchEvent(element, type, eventInit), deadline);
16257
16355
  }
16258
16356
  /**
16259
16357
  * Pinned 26a9e47 client/frame.ts and server/frames.ts default to load,
@@ -16266,15 +16364,16 @@ var PageImpl = class PageImpl {
16266
16364
  */
16267
16365
  async goto(url, options = {}) {
16268
16366
  for (const [key, value] of Object.entries(options)) if (!["timeout", "waitUntil"].includes(key) && value !== void 0) throw new Error(`Unsupported Playwright option: goto.${key}`);
16269
- const waitUntil = options.waitUntil ?? "load";
16270
- if (![
16271
- "commit",
16272
- "domcontentloaded",
16273
- "load"
16274
- ].includes(waitUntil)) throw new Error(`Unsupported waitUntil value: ${waitUntil}`);
16367
+ const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
16368
+ if (waitUntil === "networkidle") throw new Error(`Unsupported waitUntil value: ${waitUntil}`);
16275
16369
  const timeout = this.resolveTimeout(options.timeout, DEFAULT_NAVIGATION_TIMEOUT, true);
16276
16370
  if (typeof url !== "string") throw new Error("goto URL must be a string");
16277
- const target = new URL(url, this.document.baseURI);
16371
+ let target;
16372
+ try {
16373
+ target = new URL(url, this.document.baseURI);
16374
+ } catch {
16375
+ throw new Error("page.goto: Cannot navigate to invalid URL");
16376
+ }
16278
16377
  if (![
16279
16378
  "http:",
16280
16379
  "https:",
@@ -16321,10 +16420,12 @@ var PageImpl = class PageImpl {
16321
16420
  * and rendering. There is no frame traversal or protocol transport here.
16322
16421
  */
16323
16422
  async ariaSnapshot(options = {}) {
16324
- assertAriaSnapshotOptions(options);
16325
- if (options.signal?.aborted) throw queryAborted(options.signal);
16326
- await this.waitForDocumentParser(options);
16327
- return this.injectedAriaSnapshot(this.document.body ?? this.document.documentElement, options);
16423
+ return withAbortPrefix("page.ariaSnapshot", async () => {
16424
+ assertAriaSnapshotOptions(options);
16425
+ if (options.signal?.aborted) throw actionAborted(options.signal, false);
16426
+ await this.waitForDocumentParser(options);
16427
+ return this.injectedAriaSnapshot(this.document.body ?? this.document.documentElement, options);
16428
+ });
16328
16429
  }
16329
16430
  injectedAriaSnapshot(element, options = {}) {
16330
16431
  return this.injected.ariaSnapshot(element, {
@@ -16346,7 +16447,7 @@ var PageImpl = class PageImpl {
16346
16447
  else resolve();
16347
16448
  };
16348
16449
  const ready = () => settle();
16349
- const aborted = () => settle(queryAborted(options.signal));
16450
+ const aborted = () => settle(actionAborted(options.signal, true));
16350
16451
  this.window.addEventListener("DOMContentLoaded", ready, { once: true });
16351
16452
  options.signal?.addEventListener("abort", aborted, { once: true });
16352
16453
  if (timeout > 0) timeoutId = this.window.setTimeout(() => settle(new AdapterTimeoutError(`page.ariaSnapshot: Timeout ${timeout}ms exceeded.`)), timeout);
@@ -16512,17 +16613,25 @@ var PageImpl = class PageImpl {
16512
16613
  expiresAt: effectiveTimeout === 0 ? Infinity : Date.now() + effectiveTimeout
16513
16614
  };
16514
16615
  }
16616
+ attachActionSignal(deadline, signal) {
16617
+ deadline.signal = signal;
16618
+ if (signal?.aborted) throw actionAborted(signal, false);
16619
+ }
16515
16620
  assertActionDeadline(deadline, actionName) {
16621
+ if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
16516
16622
  if (deadline && Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`${actionName}: Timeout ${deadline.timeout}ms exceeded.`);
16517
16623
  }
16518
16624
  checkKeyboardActionDeadline(deadline) {
16519
16625
  this.assertActionDeadline(deadline, "press");
16520
16626
  }
16627
+ async waitKeyboardDelay(durationMs, deadline) {
16628
+ await this.waitWithinActionDeadline(durationMs, deadline, "press");
16629
+ }
16521
16630
  async waitWithinActionDeadline(durationMs, deadline, actionName) {
16522
16631
  this.assertActionDeadline(deadline, actionName);
16523
16632
  if (!durationMs || durationMs <= 0) return;
16524
16633
  const remaining = deadline ? deadline.expiresAt - Date.now() : durationMs;
16525
- await this.wait(Math.min(durationMs, remaining));
16634
+ if (!await waitForExpectationRetry(this.window, Math.min(durationMs, remaining), deadline?.signal) && deadline?.signal) throw actionAborted(deadline.signal, true);
16526
16635
  this.assertActionDeadline(deadline, actionName);
16527
16636
  }
16528
16637
  async wait(durationMs) {
@@ -16566,9 +16675,7 @@ var PageImpl = class PageImpl {
16566
16675
  return this.queryState(selector, "editable", options, true, label);
16567
16676
  }
16568
16677
  locatorIsVisible(selector, label, options) {
16569
- assertQueryOptions(options, false);
16570
- this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16571
- if (options?.signal?.aborted) throw queryAborted(options.signal);
16678
+ assertQueryOptions(options, ["timeout"]);
16572
16679
  const element = this.resolveLocatorElement(selector, true);
16573
16680
  if (!element) return false;
16574
16681
  return this.elementState(element, "visible").matches;
@@ -16578,7 +16685,7 @@ var PageImpl = class PageImpl {
16578
16685
  }
16579
16686
  async locatorAriaSnapshot(selector, label, options = {}) {
16580
16687
  assertAriaSnapshotOptions(options);
16581
- if (options.signal?.aborted) throw queryAborted(options.signal);
16688
+ if (options.signal?.aborted) throw actionAborted(options.signal, false);
16582
16689
  if (options.mode === "ai") return this.injectedAriaSnapshot(this.queryElement(selector, label, true), options);
16583
16690
  return this.query(selector, label, {
16584
16691
  signal: options.signal,
@@ -16635,13 +16742,16 @@ var PageImpl = class PageImpl {
16635
16742
  const state = options.state ?? "visible";
16636
16743
  const timeout = this.resolveTimeout(options.timeout, DEFAULT_ACTION_TIMEOUT);
16637
16744
  const deadline = timeout === 0 ? Infinity : Date.now() + timeout;
16745
+ const signal = options.signal;
16746
+ if (signal?.aborted) throw actionAborted(signal, false);
16638
16747
  while (true) {
16639
16748
  const element = root instanceof this.window.Element ? this.resolveWithinElement(root, selector, options.strict === true) : this.resolveLocatorElement(selector, options.strict === true);
16640
16749
  const visible = !!element && this.elementState(element, "visible").matches === true;
16641
16750
  if (state === "attached" && element || state === "visible" && visible) return this.elementHandleFor(element);
16642
16751
  if (state === "detached" && !element || state === "hidden" && !visible) return null;
16643
16752
  if (Date.now() >= deadline) throw new AdapterTimeoutError(`page.waitForSelector: Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)} to be ${state}`);
16644
- await this.wait(Math.min(QUERY_RETRY_DELAY, deadline - Date.now()));
16753
+ const delay = Math.min(QUERY_RETRY_DELAY, deadline - Date.now());
16754
+ if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
16645
16755
  }
16646
16756
  }
16647
16757
  async elementMatchesState(element, state) {
@@ -16658,10 +16768,14 @@ var PageImpl = class PageImpl {
16658
16768
  return result.matches;
16659
16769
  }
16660
16770
  async query(selector, label, options, strict, evaluate, actionDeadline) {
16661
- assertQueryOptions(options, !strict);
16771
+ assertQueryOptions(options, strict ? ["signal", "timeout"] : [
16772
+ "signal",
16773
+ "strict",
16774
+ "timeout"
16775
+ ]);
16662
16776
  const timeout = actionDeadline?.timeout ?? this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16663
16777
  const signal = options?.signal;
16664
- if (signal?.aborted) throw queryAborted(signal);
16778
+ if (signal?.aborted) throw actionAborted(signal, false);
16665
16779
  const deadline = actionDeadline?.expiresAt ?? (timeout === 0 ? Infinity : Date.now() + timeout);
16666
16780
  while (true) try {
16667
16781
  return await evaluate(this.queryElement(selector, label, strict || options?.strict === true));
@@ -16670,7 +16784,7 @@ var PageImpl = class PageImpl {
16670
16784
  const remaining = deadline - Date.now();
16671
16785
  if (remaining <= 0) throw new AdapterTimeoutError(`Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)}`, { cause: error });
16672
16786
  const delay = Math.min(QUERY_RETRY_DELAY, remaining);
16673
- if (!await waitForExpectationRetry(this.window, delay, signal)) throw queryAborted(signal);
16787
+ if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
16674
16788
  }
16675
16789
  }
16676
16790
  queryElement(selector, label, strict) {
@@ -16693,16 +16807,23 @@ var PageImpl = class PageImpl {
16693
16807
  throw new Error(`Element is not ${result.missingState}`);
16694
16808
  }
16695
16809
  async waitForActionDeadline(operation, deadline, timeoutError) {
16696
- if (!deadline || deadline.expiresAt === Infinity) return operation;
16697
- if (Date.now() >= deadline.expiresAt) throw timeoutError();
16810
+ if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
16811
+ if (deadline && Date.now() >= deadline.expiresAt) throw timeoutError();
16812
+ if (!deadline) return operation;
16698
16813
  let timeoutHandle;
16814
+ let onAbort;
16699
16815
  try {
16700
16816
  return await new Promise((resolve, reject) => {
16701
- timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
16817
+ if (deadline.expiresAt !== Infinity) timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
16818
+ if (deadline.signal) {
16819
+ onAbort = () => reject(actionAborted(deadline.signal, true));
16820
+ deadline.signal.addEventListener("abort", onAbort, { once: true });
16821
+ }
16702
16822
  operation.then(resolve, reject);
16703
16823
  });
16704
16824
  } finally {
16705
16825
  if (timeoutHandle !== void 0) this.window.clearTimeout(timeoutHandle);
16826
+ if (onAbort) deadline.signal?.removeEventListener("abort", onAbort);
16706
16827
  }
16707
16828
  }
16708
16829
  actionabilityDeadlineError(element, states) {
@@ -16717,7 +16838,7 @@ var PageImpl = class PageImpl {
16717
16838
  }
16718
16839
  return /* @__PURE__ */ new Error("Element is not stable");
16719
16840
  }
16720
- async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions) {
16841
+ async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions, strict = pointerOptions?.strict ?? true) {
16721
16842
  let lastError;
16722
16843
  let retry = 0;
16723
16844
  const log = [];
@@ -16729,7 +16850,7 @@ var PageImpl = class PageImpl {
16729
16850
  while (true) {
16730
16851
  if (Date.now() >= deadline.expiresAt) throwTimeout();
16731
16852
  try {
16732
- const element = this.resolvePointerElement(selector, label, pointerOptions?.strict ?? true);
16853
+ const element = this.resolvePointerElement(selector, label, strict);
16733
16854
  if (pointerOptions && !pointerOptions.force) log.push(` - waiting for element to be ${states.includes("enabled") ? "visible, enabled and stable" : "visible and stable"}`);
16734
16855
  if (!pointerOptions?.force) await this.ensureActionable(element, states, deadline);
16735
16856
  if (Date.now() >= deadline.expiresAt) throwTimeout();
@@ -16776,7 +16897,12 @@ var PageImpl = class PageImpl {
16776
16897
  if (log.length > 60) log.splice(0, log.length - 60);
16777
16898
  }
16778
16899
  if (remaining <= 0) throw timeoutError();
16779
- await this.wait(Math.min(delay, remaining));
16900
+ try {
16901
+ await this.waitWithinActionDeadline(Math.min(delay, remaining), deadline, actionName);
16902
+ } catch (error) {
16903
+ if (error instanceof AdapterTimeoutError) throw timeoutError();
16904
+ throw error;
16905
+ }
16780
16906
  }
16781
16907
  }
16782
16908
  }
@@ -16969,8 +17095,8 @@ var PageImpl = class PageImpl {
16969
17095
  this.assertActionDeadline(deadline, "press");
16970
17096
  this.insertPressedText(element, text, inputType, eventData, deadline);
16971
17097
  }
16972
- async insertTextSelector(selector, text, label, deadline) {
16973
- const element = await this.query(selector, label, { timeout: deadline.timeout }, true, (candidate) => candidate, deadline);
17098
+ async insertTextSelector(selector, text, label, deadline, strict = true) {
17099
+ const element = await this.query(selector, label, { timeout: deadline.timeout }, strict, (candidate) => candidate, deadline);
16974
17100
  this.assertActionDeadline(deadline, "press");
16975
17101
  this.focusElement(element);
16976
17102
  this.insertKeyboardText(element, text, "insertText", text, deadline);
@@ -17213,25 +17339,49 @@ var BrowserKeyboard = class {
17213
17339
  async up(key, deadline) {
17214
17340
  await this.upForTarget(key, deadline);
17215
17341
  }
17216
- async insertText(text) {
17217
- this.page.insertKeyboardText(this.activeTarget(), text);
17342
+ async insertText(text, deadline) {
17343
+ this.page.insertKeyboardText(this.activeTarget(), text, "insertText", text, deadline);
17218
17344
  }
17219
- async type(text, options = {}) {
17345
+ async type(text, options = {}, deadline) {
17220
17346
  const delay = options.delay || void 0;
17221
- for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay });
17347
+ for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay }, deadline);
17222
17348
  else {
17223
- if (delay) await this.wait(delay);
17224
- await this.insertText(character);
17349
+ if (delay) await this.page.waitKeyboardDelay(delay, deadline);
17350
+ await this.insertText(character, deadline);
17225
17351
  }
17226
17352
  }
17227
17353
  async press(key, options = {}, deadline) {
17228
17354
  const tokens = splitKeyboardShortcut(key);
17229
17355
  const target = tokens.at(-1);
17230
- for (const modifier of tokens.slice(0, -1)) await this.down(modifier, deadline);
17231
- await this.down(target, deadline);
17232
- if (options.delay) await this.wait(options.delay, deadline);
17233
- await this.up(target, deadline);
17234
- for (const modifier of tokens.slice(0, -1).reverse()) await this.up(modifier, deadline);
17356
+ const modifiers = tokens.slice(0, -1);
17357
+ const held = /* @__PURE__ */ new Set();
17358
+ try {
17359
+ for (const modifier of modifiers) {
17360
+ held.add(modifier);
17361
+ await this.down(modifier, deadline);
17362
+ }
17363
+ held.add(target);
17364
+ await this.down(target, deadline);
17365
+ if (options.delay) await this.page.waitKeyboardDelay(options.delay, deadline);
17366
+ await this.up(target, deadline);
17367
+ held.delete(target);
17368
+ for (const modifier of modifiers.reverse()) {
17369
+ await this.up(modifier, deadline);
17370
+ held.delete(modifier);
17371
+ }
17372
+ } catch (error) {
17373
+ this.releaseKeys(held);
17374
+ throw error;
17375
+ }
17376
+ }
17377
+ releaseKeys(keys) {
17378
+ for (const key of keys) {
17379
+ const description = keyboardLayout.get(resolveKeyboardKey(key, this.page.window));
17380
+ if (!description) continue;
17381
+ this.pressedKeys.delete(description.code);
17382
+ this.keydownState.delete(description.code);
17383
+ if (isModifier(description.key)) this.pressedModifiers.delete(description.key);
17384
+ }
17235
17385
  }
17236
17386
  async downForTarget(key, deadline) {
17237
17387
  this.page.checkKeyboardActionDeadline(deadline);
@@ -17288,13 +17438,6 @@ var BrowserKeyboard = class {
17288
17438
  };
17289
17439
  return description;
17290
17440
  }
17291
- async wait(delay, deadline) {
17292
- this.page.checkKeyboardActionDeadline(deadline);
17293
- const remaining = deadline ? Math.max(0, deadline.expiresAt - Date.now()) : delay;
17294
- if (deadline && remaining <= 0) this.page.checkKeyboardActionDeadline(deadline);
17295
- await new Promise((resolve) => this.page.window.setTimeout(resolve, Math.min(delay, remaining)));
17296
- this.page.checkKeyboardActionDeadline(deadline);
17297
- }
17298
17441
  async waitForKeyboardPhase(deadline) {
17299
17442
  this.page.checkKeyboardActionDeadline(deadline);
17300
17443
  await new Promise((resolve) => this.page.window.setTimeout(resolve));
@@ -17411,12 +17554,17 @@ function validateTimeout(timeout, name) {
17411
17554
  if (typeof timeout !== "number" || timeout < 0 || !Number.isFinite(timeout)) throw new TypeError(`${name} must be a non-negative finite number`);
17412
17555
  return timeout;
17413
17556
  }
17557
+ /** Returns the normalized `delay`, unwrapped like the pointer options. */
17414
17558
  function assertPageActionOptions(method, options, supported = []) {
17415
- if (!options) return;
17416
- const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "timeout" && !supported.includes(key));
17559
+ if (!options) return void 0;
17560
+ const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "signal" && key !== "timeout" && !supported.includes(key));
17417
17561
  if (unsupported.length > 0) throw new Error(`${method}(): unsupported options: ${unsupported.join(", ")}. Unsupported Playwright option(s) are not supported by the single-document adapter.`);
17562
+ validateSignal(method, options.signal);
17418
17563
  if (options.timeout !== void 0) validateTimeout(options.timeout, `${method} timeout`);
17419
17564
  if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
17565
+ const delay = supported.includes("delay") ? validateDelay(options.delay) : void 0;
17566
+ if (supported.includes("strict") && options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
17567
+ return delay;
17420
17568
  }
17421
17569
  function assertPageDispatchEventOptions(options) {
17422
17570
  assertPageActionOptions("dispatchEvent", options, ["strict"]);
@@ -17424,6 +17572,7 @@ function assertPageDispatchEventOptions(options) {
17424
17572
  }
17425
17573
  function assertPointerActionOptions(method, options) {
17426
17574
  const supported = [
17575
+ "signal",
17427
17576
  "noWaitAfter",
17428
17577
  "position",
17429
17578
  "trial",
@@ -17476,19 +17625,22 @@ function assertPointerActionOptions(method, options) {
17476
17625
  }
17477
17626
  function assertAriaSnapshotOptions(options) {
17478
17627
  queryTimeout(options.timeout);
17479
- if (options.signal !== void 0 && !(options.signal instanceof AbortSignal)) throw new TypeError("ARIA snapshot signal must be an AbortSignal");
17628
+ validateSignal("ARIA snapshot", options.signal);
17480
17629
  }
17481
- function assertQueryOptions(options, allowsStrict) {
17630
+ function assertQueryOptions(options, allowed) {
17482
17631
  if (!options) return;
17483
- for (const key of Object.keys(options)) if (key !== "signal" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported query option: ${key}`);
17484
- if (options.signal !== void 0 && !(options.signal instanceof AbortSignal)) throw new TypeError("Query signal must be an AbortSignal");
17485
- if (!allowsStrict && "strict" in options) throw new Error("Locator query options do not support strict");
17632
+ for (const key of Object.keys(options)) {
17633
+ if (key === "signal" && options.signal === void 0) continue;
17634
+ if (!allowed.includes(key)) throw new Error(`Unsupported query option: ${key}`);
17635
+ }
17636
+ validateSignal("Query", options.signal);
17486
17637
  }
17487
17638
  function assertDollarOptions(options) {
17488
17639
  for (const key of Object.keys(options)) if (key !== "strict") throw new Error(`Unsupported query option: ${key}`);
17489
17640
  }
17490
17641
  function assertWaitForSelectorOptions(options, allowsStrict) {
17491
- for (const key of Object.keys(options)) if (key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
17642
+ for (const key of Object.keys(options)) if (key !== "signal" && key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
17643
+ validateSignal("waitForSelector", options.signal);
17492
17644
  if (!allowsStrict && "strict" in options) throw new Error("ElementHandle waitForSelector does not support strict");
17493
17645
  if (options.state !== void 0 && ![
17494
17646
  "attached",
@@ -17510,6 +17662,21 @@ function assertElementHandleStateOptions(state, options) {
17510
17662
  for (const key of Object.keys(options)) if (key !== "timeout") throw new Error(`Unsupported waitForElementState option: ${key}`);
17511
17663
  if (options.timeout !== void 0) validateTimeout(options.timeout, "waitForElementState timeout");
17512
17664
  }
17665
+ /**
17666
+ * Pinned 26a9e47 client/frame.ts `verifyLoadState`: accepts the four lifecycle
17667
+ * events, keeps the `networkidle0` alias, and rejects anything else with the
17668
+ * client's wording before the navigation is requested.
17669
+ */
17670
+ function verifyLoadState(name, waitUntil) {
17671
+ if (waitUntil === "networkidle0") waitUntil = "networkidle";
17672
+ if (![
17673
+ "load",
17674
+ "domcontentloaded",
17675
+ "networkidle",
17676
+ "commit"
17677
+ ].includes(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
17678
+ return waitUntil;
17679
+ }
17513
17680
  function isRetryableQueryError(error) {
17514
17681
  const message = asError(error).message;
17515
17682
  return message.startsWith("No elements found for locator") || message === "Element is not connected";
@@ -17525,8 +17692,24 @@ function presentOriginalXPath(error, selector) {
17525
17692
  if (rewritten === source.message) return source;
17526
17693
  return new Error(rewritten, { cause: source });
17527
17694
  }
17528
- function queryAborted(signal) {
17529
- return /* @__PURE__ */ new Error(`Query was aborted: ${abortReason(signal)}`);
17695
+ function actionAborted(signal, inFlight) {
17696
+ const reason = abortReason(signal);
17697
+ const error = new Error(inFlight ? `${reason}\nCall log:\n - operation was aborted: ${reason}` : "The operation was aborted", { cause: signal.reason });
17698
+ error.name = "AbortError";
17699
+ return error;
17700
+ }
17701
+ async function withAbortPrefix(apiName, run) {
17702
+ try {
17703
+ return await run();
17704
+ } catch (error) {
17705
+ throw prefixAbortError(error, apiName);
17706
+ }
17707
+ }
17708
+ function prefixAbortError(error, apiName) {
17709
+ const result = asError(error);
17710
+ if (result.name !== "AbortError") return error;
17711
+ result.message = `${apiName}: ${result.message}`;
17712
+ return result;
17530
17713
  }
17531
17714
  function unknownKey(value) {
17532
17715
  throw new Error(`Unknown key: "${value}"`);