playwright-core 1.54.0-alpha-2025-06-24 → 1.54.0-alpha-2025-06-25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ThirdPartyNotices.txt +3 -3
- package/browsers.json +4 -4
- package/lib/cli/programWithTestStub.js +1 -1
- package/lib/client/elementHandle.js +0 -4
- package/lib/client/locator.js +2 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/protocol/validator.js +6 -4
- package/lib/server/dispatchers/elementHandlerDispatcher.js +0 -3
- package/lib/server/dispatchers/frameDispatcher.js +3 -0
- package/lib/server/dom.js +4 -29
- package/lib/server/frames.js +54 -35
- package/lib/server/progress.js +29 -10
- package/lib/utils/isomorphic/protocolMetainfo.js +1 -1
- package/lib/utilsBundleImpl/index.js +160 -150
- package/lib/vite/traceViewer/assets/{codeMirrorModule--amfWN3K.js → codeMirrorModule-KhY1IY1h.js} +1 -1
- package/lib/vite/traceViewer/assets/{defaultSettingsView-BFAIqAv2.js → defaultSettingsView-h9mbAVJF.js} +45 -45
- package/lib/vite/traceViewer/{index.amRtOpxT.js → index.Ckw7w8kC.js} +1 -1
- package/lib/vite/traceViewer/index.html +2 -2
- package/lib/vite/traceViewer/uiMode.html +2 -2
- package/lib/vite/traceViewer/{uiMode.hufuL2u6.js → uiMode.wzqlDRzc.js} +1 -1
- package/package.json +1 -1
|
@@ -1657,6 +1657,12 @@ import_validatorPrimitives.scheme.FrameFrameElementParams = (0, import_validator
|
|
|
1657
1657
|
import_validatorPrimitives.scheme.FrameFrameElementResult = (0, import_validatorPrimitives.tObject)({
|
|
1658
1658
|
element: (0, import_validatorPrimitives.tChannel)(["ElementHandle"])
|
|
1659
1659
|
});
|
|
1660
|
+
import_validatorPrimitives.scheme.FrameGenerateLocatorStringParams = (0, import_validatorPrimitives.tObject)({
|
|
1661
|
+
selector: import_validatorPrimitives.tString
|
|
1662
|
+
});
|
|
1663
|
+
import_validatorPrimitives.scheme.FrameGenerateLocatorStringResult = (0, import_validatorPrimitives.tObject)({
|
|
1664
|
+
value: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString)
|
|
1665
|
+
});
|
|
1660
1666
|
import_validatorPrimitives.scheme.FrameHighlightParams = (0, import_validatorPrimitives.tObject)({
|
|
1661
1667
|
selector: import_validatorPrimitives.tString
|
|
1662
1668
|
});
|
|
@@ -2050,10 +2056,6 @@ import_validatorPrimitives.scheme.ElementHandleFillParams = (0, import_validator
|
|
|
2050
2056
|
import_validatorPrimitives.scheme.ElementHandleFillResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
2051
2057
|
import_validatorPrimitives.scheme.ElementHandleFocusParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
2052
2058
|
import_validatorPrimitives.scheme.ElementHandleFocusResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
2053
|
-
import_validatorPrimitives.scheme.ElementHandleGenerateLocatorStringParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
2054
|
-
import_validatorPrimitives.scheme.ElementHandleGenerateLocatorStringResult = (0, import_validatorPrimitives.tObject)({
|
|
2055
|
-
value: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString)
|
|
2056
|
-
});
|
|
2057
2059
|
import_validatorPrimitives.scheme.ElementHandleGetAttributeParams = (0, import_validatorPrimitives.tObject)({
|
|
2058
2060
|
name: import_validatorPrimitives.tString
|
|
2059
2061
|
});
|
|
@@ -55,9 +55,6 @@ class ElementHandleDispatcher extends import_jsHandleDispatcher.JSHandleDispatch
|
|
|
55
55
|
const frame = await this._elementHandle.contentFrame();
|
|
56
56
|
return { frame: frame ? import_frameDispatcher.FrameDispatcher.from(this._browserContextDispatcher(), frame) : void 0 };
|
|
57
57
|
}
|
|
58
|
-
async generateLocatorString(params, metadata) {
|
|
59
|
-
return { value: await this._elementHandle.generateLocatorString() };
|
|
60
|
-
}
|
|
61
58
|
async getAttribute(params, metadata) {
|
|
62
59
|
const value = await this._elementHandle.getAttribute(metadata, params.name);
|
|
63
60
|
return { value: value === null ? void 0 : value };
|
|
@@ -144,6 +144,9 @@ class FrameDispatcher extends import_dispatcher.Dispatcher {
|
|
|
144
144
|
async innerHTML(params, metadata) {
|
|
145
145
|
return { value: await this._frame.innerHTML(metadata, params.selector, params) };
|
|
146
146
|
}
|
|
147
|
+
async generateLocatorString(params, metadata) {
|
|
148
|
+
return { value: await this._frame.generateLocatorString(metadata, params.selector) };
|
|
149
|
+
}
|
|
147
150
|
async getAttribute(params, metadata) {
|
|
148
151
|
const value = await this._frame.getAttribute(metadata, params.selector, params.name, params);
|
|
149
152
|
return { value: value === null ? void 0 : value };
|
package/lib/server/dom.js
CHANGED
|
@@ -161,35 +161,6 @@ class ElementHandle extends js.JSHandle {
|
|
|
161
161
|
return null;
|
|
162
162
|
return this._page.delegate.getContentFrame(this);
|
|
163
163
|
}
|
|
164
|
-
async generateLocatorString() {
|
|
165
|
-
const selectors = await this._generateSelectorString();
|
|
166
|
-
if (!selectors.length)
|
|
167
|
-
return;
|
|
168
|
-
return (0, import_utils.asLocator)("javascript", selectors.reverse().join(" >> internal:control=enter-frame >> "));
|
|
169
|
-
}
|
|
170
|
-
async _generateSelectorString() {
|
|
171
|
-
const selector = await this.evaluateInUtility(async ([injected, node]) => {
|
|
172
|
-
return injected.generateSelectorSimple(node);
|
|
173
|
-
}, {});
|
|
174
|
-
if (selector === "error:notconnected")
|
|
175
|
-
return [];
|
|
176
|
-
let frame = this._frame;
|
|
177
|
-
const result = [selector];
|
|
178
|
-
while (frame?.parentFrame()) {
|
|
179
|
-
const frameElement = await frame.frameElement();
|
|
180
|
-
if (frameElement) {
|
|
181
|
-
const selector2 = await frameElement.evaluateInUtility(async ([injected, node]) => {
|
|
182
|
-
return injected.generateSelectorSimple(node);
|
|
183
|
-
}, {});
|
|
184
|
-
frameElement.dispose();
|
|
185
|
-
if (selector2 === "error:notconnected")
|
|
186
|
-
return [];
|
|
187
|
-
result.push(selector2);
|
|
188
|
-
}
|
|
189
|
-
frame = frame.parentFrame();
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
164
|
async getAttribute(metadata, name) {
|
|
194
165
|
return this._frame.getAttribute(metadata, ":scope", name, { timeout: 0 }, this);
|
|
195
166
|
}
|
|
@@ -321,6 +292,10 @@ class ElementHandle extends js.JSHandle {
|
|
|
321
292
|
progress.log(" did not find some options");
|
|
322
293
|
continue;
|
|
323
294
|
}
|
|
295
|
+
if (result === "error:optionnotenabled") {
|
|
296
|
+
progress.log(" option being selected is not enabled");
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
324
299
|
if (typeof result === "object" && "hitTargetDescription" in result) {
|
|
325
300
|
progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
|
|
326
301
|
continue;
|
package/lib/server/frames.js
CHANGED
|
@@ -1015,6 +1015,35 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1015
1015
|
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._blur(progress)));
|
|
1016
1016
|
}, options.timeout);
|
|
1017
1017
|
}
|
|
1018
|
+
async generateLocatorString(metadata, selector) {
|
|
1019
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1020
|
+
return controller.run(async (progress) => {
|
|
1021
|
+
const element = await progress.race(this.selectors.query(selector));
|
|
1022
|
+
if (!element)
|
|
1023
|
+
throw new Error(`No element matching ${this._asLocator(selector)}`);
|
|
1024
|
+
const generated = await progress.race(element.evaluateInUtility(async ([injected, node]) => {
|
|
1025
|
+
return injected.generateSelectorSimple(node);
|
|
1026
|
+
}, {}));
|
|
1027
|
+
if (!generated)
|
|
1028
|
+
throw new Error(`Unable to generate locator for ${this._asLocator(selector)}`);
|
|
1029
|
+
let frame = element._frame;
|
|
1030
|
+
const result = [generated];
|
|
1031
|
+
while (frame?.parentFrame()) {
|
|
1032
|
+
const frameElement = await progress.race(frame.frameElement());
|
|
1033
|
+
if (frameElement) {
|
|
1034
|
+
const generated2 = await progress.race(frameElement.evaluateInUtility(async ([injected, node]) => {
|
|
1035
|
+
return injected.generateSelectorSimple(node);
|
|
1036
|
+
}, {}));
|
|
1037
|
+
frameElement.dispose();
|
|
1038
|
+
if (generated2 === "error:notconnected" || !generated2)
|
|
1039
|
+
throw new Error(`Unable to generate locator for ${this._asLocator(selector)}`);
|
|
1040
|
+
result.push(generated2);
|
|
1041
|
+
}
|
|
1042
|
+
frame = frame.parentFrame();
|
|
1043
|
+
}
|
|
1044
|
+
return (0, import_utils.asLocator)(this._page.browserContext._browser.sdkLanguage(), result.reverse().join(" >> internal:control=enter-frame >> "));
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1018
1047
|
async textContent(metadata, selector, options, scope) {
|
|
1019
1048
|
return this._callOnElementOnceMatches(metadata, selector, (injected, element) => element.textContent, void 0, options, scope);
|
|
1020
1049
|
}
|
|
@@ -1162,43 +1191,32 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1162
1191
|
return result;
|
|
1163
1192
|
}
|
|
1164
1193
|
async _expectImpl(metadata, selector, options) {
|
|
1194
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1165
1195
|
const lastIntermediateResult = { isSet: false };
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
1173
|
-
await this._page.performActionPreChecks(progress);
|
|
1174
|
-
}, timeout);
|
|
1196
|
+
return await controller.run(async (progress) => {
|
|
1197
|
+
progress.log(`${(0, import_utils.renderTitleForCall)(metadata)}${options.timeout ? ` with timeout ${options.timeout}ms` : ""}`);
|
|
1198
|
+
if (selector)
|
|
1199
|
+
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
1200
|
+
await this._page.performActionPreChecks(progress);
|
|
1201
|
+
progress.legacyDisableTimeout();
|
|
1175
1202
|
try {
|
|
1176
|
-
const resultOneShot = await
|
|
1177
|
-
return await this._expectInternal(progress, selector, options, lastIntermediateResult);
|
|
1178
|
-
});
|
|
1203
|
+
const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
|
|
1179
1204
|
if (resultOneShot.matches !== options.isNot)
|
|
1180
1205
|
return resultOneShot;
|
|
1181
1206
|
} catch (e) {
|
|
1182
1207
|
if (this.isNonRetriableError(e))
|
|
1183
1208
|
throw e;
|
|
1184
1209
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
return
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
if (matches === options.isNot) {
|
|
1196
|
-
return continuePolling;
|
|
1197
|
-
}
|
|
1198
|
-
return { matches, received };
|
|
1199
|
-
});
|
|
1200
|
-
}, timeout);
|
|
1201
|
-
} catch (e) {
|
|
1210
|
+
progress.legacyEnableTimeout();
|
|
1211
|
+
return await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
|
|
1212
|
+
await this._page.performActionPreChecks(progress);
|
|
1213
|
+
const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
|
|
1214
|
+
if (matches === options.isNot) {
|
|
1215
|
+
return continuePolling;
|
|
1216
|
+
}
|
|
1217
|
+
return { matches, received };
|
|
1218
|
+
});
|
|
1219
|
+
}, options.timeout).catch((e) => {
|
|
1202
1220
|
if (js.isJavaScriptErrorInEvaluate(e) || (0, import_selectorParser.isInvalidSelectorError)(e))
|
|
1203
1221
|
throw e;
|
|
1204
1222
|
const result = { matches: options.isNot, log: (0, import_callLog.compressCallLog)(metadata.log) };
|
|
@@ -1207,15 +1225,16 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1207
1225
|
if (e instanceof import_errors.TimeoutError)
|
|
1208
1226
|
result.timedOut = true;
|
|
1209
1227
|
return result;
|
|
1210
|
-
}
|
|
1228
|
+
});
|
|
1211
1229
|
}
|
|
1212
|
-
async _expectInternal(progress, selector, options, lastIntermediateResult) {
|
|
1213
|
-
const
|
|
1230
|
+
async _expectInternal(progress, selector, options, lastIntermediateResult, noAbort) {
|
|
1231
|
+
const race = (p) => noAbort ? p : progress.race(p);
|
|
1232
|
+
const selectorInFrame = selector ? await race(this.selectors.resolveFrameForSelector(selector, { strict: true })) : void 0;
|
|
1214
1233
|
const { frame, info } = selectorInFrame || { frame: this, info: void 0 };
|
|
1215
1234
|
const world = options.expression === "to.have.property" ? "main" : info?.world ?? "utility";
|
|
1216
|
-
const context = await
|
|
1217
|
-
const injected = await
|
|
1218
|
-
const { log, matches, received, missingReceived } = await
|
|
1235
|
+
const context = await race(frame._context(world));
|
|
1236
|
+
const injected = await race(context.injectedScript());
|
|
1237
|
+
const { log, matches, received, missingReceived } = await race(injected.evaluate(async (injected2, { info: info2, options: options2, callId }) => {
|
|
1219
1238
|
const elements = info2 ? injected2.querySelectorAll(info2.parsed, document) : [];
|
|
1220
1239
|
if (callId)
|
|
1221
1240
|
injected2.markTargetElements(new Set(elements), callId);
|
package/lib/server/progress.js
CHANGED
|
@@ -61,6 +61,24 @@ class ProgressController {
|
|
|
61
61
|
(0, import_utils.assert)(this._state === "before");
|
|
62
62
|
this._state = "running";
|
|
63
63
|
this.sdkObject.attribution.context?._activeProgressControllers.add(this);
|
|
64
|
+
const deadline = timeout ? Math.min((0, import_utils.monotonicTime)() + timeout, 2147483647) : 0;
|
|
65
|
+
const timeoutError = new import_errors.TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
|
66
|
+
let timer;
|
|
67
|
+
const startTimer = () => {
|
|
68
|
+
if (!deadline)
|
|
69
|
+
return;
|
|
70
|
+
const onTimeout = () => {
|
|
71
|
+
if (this._state === "running") {
|
|
72
|
+
this._state = { error: timeoutError };
|
|
73
|
+
this._forceAbortPromise.reject(timeoutError);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const remaining = deadline - (0, import_utils.monotonicTime)();
|
|
77
|
+
if (remaining <= 0)
|
|
78
|
+
onTimeout();
|
|
79
|
+
else
|
|
80
|
+
timer = setTimeout(onTimeout, remaining);
|
|
81
|
+
};
|
|
64
82
|
const progress = {
|
|
65
83
|
log: (message) => {
|
|
66
84
|
if (this._state === "running")
|
|
@@ -94,18 +112,19 @@ class ProgressController {
|
|
|
94
112
|
let timer2;
|
|
95
113
|
const promise = new Promise((f) => timer2 = setTimeout(f, timeout2));
|
|
96
114
|
return progress.race(promise).finally(() => clearTimeout(timer2));
|
|
115
|
+
},
|
|
116
|
+
legacyDisableTimeout: () => {
|
|
117
|
+
if (this._strictMode)
|
|
118
|
+
return;
|
|
119
|
+
clearTimeout(timer);
|
|
120
|
+
},
|
|
121
|
+
legacyEnableTimeout: () => {
|
|
122
|
+
if (this._strictMode)
|
|
123
|
+
return;
|
|
124
|
+
startTimer();
|
|
97
125
|
}
|
|
98
126
|
};
|
|
99
|
-
|
|
100
|
-
if (timeout) {
|
|
101
|
-
const timeoutError = new import_errors.TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
|
102
|
-
timer = setTimeout(() => {
|
|
103
|
-
if (this._state === "running") {
|
|
104
|
-
this._state = { error: timeoutError };
|
|
105
|
-
this._forceAbortPromise.reject(timeoutError);
|
|
106
|
-
}
|
|
107
|
-
}, Math.min(timeout, 2147483647));
|
|
108
|
-
}
|
|
127
|
+
startTimer();
|
|
109
128
|
try {
|
|
110
129
|
const promise = task(progress);
|
|
111
130
|
const result = this._strictMode ? await promise : await Promise.race([promise, this._forceAbortPromise]);
|
|
@@ -159,6 +159,7 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
|
|
159
159
|
["Frame.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pausesBeforeInput: true }],
|
|
160
160
|
["Frame.focus", { title: "Focus", slowMo: true, snapshot: true }],
|
|
161
161
|
["Frame.frameElement", { internal: true }],
|
|
162
|
+
["Frame.generateLocatorString", { internal: true }],
|
|
162
163
|
["Frame.highlight", { internal: true }],
|
|
163
164
|
["Frame.getAttribute", { internal: true, snapshot: true }],
|
|
164
165
|
["Frame.goto", { title: 'Navigate to "{url}"', slowMo: true, snapshot: true }],
|
|
@@ -212,7 +213,6 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
|
|
212
213
|
["ElementHandle.dispatchEvent", { title: "Dispatch event", slowMo: true, snapshot: true }],
|
|
213
214
|
["ElementHandle.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pausesBeforeInput: true }],
|
|
214
215
|
["ElementHandle.focus", { title: "Focus", slowMo: true, snapshot: true }],
|
|
215
|
-
["ElementHandle.generateLocatorString", { internal: true }],
|
|
216
216
|
["ElementHandle.getAttribute", { internal: true }],
|
|
217
217
|
["ElementHandle.hover", { title: "Hover", slowMo: true, snapshot: true, pausesBeforeInput: true }],
|
|
218
218
|
["ElementHandle.innerHTML", { title: "Get HTML", snapshot: true }],
|