chore: use progress.continuePolling instead of passing it around (#9929)
This commit is contained in:
parent
b924b7e076
commit
50f7477906
|
|
@ -952,7 +952,7 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
|
||||||
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, state, omitReturnValue, root }) => {
|
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, state, omitReturnValue, root }) => {
|
||||||
let lastElement: Element | undefined;
|
let lastElement: Element | undefined;
|
||||||
|
|
||||||
return injected.pollRaf((progress, continuePolling) => {
|
return injected.pollRaf(progress => {
|
||||||
const elements = injected.querySelectorAll(parsed, root || document);
|
const elements = injected.querySelectorAll(parsed, root || document);
|
||||||
let element: Element | undefined = elements[0];
|
let element: Element | undefined = elements[0];
|
||||||
const visible = element ? injected.isVisible(element) : false;
|
const visible = element ? injected.isVisible(element) : false;
|
||||||
|
|
@ -977,13 +977,13 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'attached':
|
case 'attached':
|
||||||
return hasElement ? element : continuePolling;
|
return hasElement ? element : progress.continuePolling;
|
||||||
case 'detached':
|
case 'detached':
|
||||||
return !hasElement ? undefined : continuePolling;
|
return !hasElement ? undefined : progress.continuePolling;
|
||||||
case 'visible':
|
case 'visible':
|
||||||
return visible ? element : continuePolling;
|
return visible ? element : progress.continuePolling;
|
||||||
case 'hidden':
|
case 'hidden':
|
||||||
return !visible ? undefined : continuePolling;
|
return !visible ? undefined : progress.continuePolling;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, { parsed: selector.parsed, strict: selector.strict, state, omitReturnValue, root });
|
}, { parsed: selector.parsed, strict: selector.strict, state, omitReturnValue, root });
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ export type NavigationEvent = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SchedulableTask<T> = (injectedScript: js.JSHandle<InjectedScript>) => Promise<js.JSHandle<InjectedScriptPoll<T>>>;
|
export type SchedulableTask<T> = (injectedScript: js.JSHandle<InjectedScript>) => Promise<js.JSHandle<InjectedScriptPoll<T>>>;
|
||||||
export type DomTaskBody<T, R, E> = (progress: InjectedScriptProgress, element: E, data: T, elements: Element[], continuePolling: symbol) => R | symbol;
|
export type DomTaskBody<T, R, E> = (progress: InjectedScriptProgress, element: E, data: T, elements: Element[]) => R | symbol;
|
||||||
|
|
||||||
export class FrameManager {
|
export class FrameManager {
|
||||||
private _page: Page;
|
private _page: Page;
|
||||||
|
|
@ -1158,7 +1158,7 @@ export class Frame extends SdkObject {
|
||||||
const controller = new ProgressController(metadata, this);
|
const controller = new ProgressController(metadata, this);
|
||||||
const querySelectorAll = options.expression === 'to.have.count' || options.expression.endsWith('.array');
|
const querySelectorAll = options.expression === 'to.have.count' || options.expression.endsWith('.array');
|
||||||
const mainWorld = options.expression === 'to.have.property';
|
const mainWorld = options.expression === 'to.have.property';
|
||||||
return await this._scheduleRerunnableTaskWithController(controller, selector, (progress, element, options, elements, continuePolling) => {
|
return await this._scheduleRerunnableTaskWithController(controller, selector, (progress, element, options, elements) => {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
// expect(locator).toBeHidden() passes when there is no element.
|
// expect(locator).toBeHidden() passes when there is no element.
|
||||||
if (!options.isNot && options.expression === 'to.be.hidden')
|
if (!options.isNot && options.expression === 'to.be.hidden')
|
||||||
|
|
@ -1181,7 +1181,7 @@ export class Frame extends SdkObject {
|
||||||
return { matches: expectsEmptyCount, received: 0 };
|
return { matches: expectsEmptyCount, received: 0 };
|
||||||
|
|
||||||
// When none of the above applies, keep waiting for the element.
|
// When none of the above applies, keep waiting for the element.
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { matches, received } = progress.injectedScript.expect(progress, element, options, elements);
|
const { matches, received } = progress.injectedScript.expect(progress, element, options, elements);
|
||||||
|
|
@ -1192,7 +1192,7 @@ export class Frame extends SdkObject {
|
||||||
progress.setIntermediateResult(received);
|
progress.setIntermediateResult(received);
|
||||||
if (!Array.isArray(received))
|
if (!Array.isArray(received))
|
||||||
progress.log(` unexpected value "${received}"`);
|
progress.log(` unexpected value "${received}"`);
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reached the expected state!
|
// Reached the expected state!
|
||||||
|
|
@ -1226,8 +1226,8 @@ export class Frame extends SdkObject {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
if (typeof polling !== 'number')
|
if (typeof polling !== 'number')
|
||||||
return injectedScript.pollRaf((progress, continuePolling) => predicate(arg) || continuePolling);
|
return injectedScript.pollRaf(progress => predicate(arg) || progress.continuePolling);
|
||||||
return injectedScript.pollInterval(polling, (progress, continuePolling) => predicate(arg) || continuePolling);
|
return injectedScript.pollInterval(polling, progress => predicate(arg) || progress.continuePolling);
|
||||||
}, { expression, isFunction, polling: options.pollingInterval, arg });
|
}, { expression, isFunction, polling: options.pollingInterval, arg });
|
||||||
return controller.run(
|
return controller.run(
|
||||||
progress => this._scheduleRerunnableHandleTask(progress, world, task),
|
progress => this._scheduleRerunnableHandleTask(progress, world, task),
|
||||||
|
|
@ -1286,7 +1286,7 @@ export class Frame extends SdkObject {
|
||||||
const callback = injected.eval(callbackText) as DomTaskBody<T, R, Element | undefined>;
|
const callback = injected.eval(callbackText) as DomTaskBody<T, R, Element | undefined>;
|
||||||
const poller = logScale ? injected.pollLogScale.bind(injected) : injected.pollRaf.bind(injected);
|
const poller = logScale ? injected.pollLogScale.bind(injected) : injected.pollRaf.bind(injected);
|
||||||
let markedElements = new Set<Element>();
|
let markedElements = new Set<Element>();
|
||||||
return poller((progress, continuePolling) => {
|
return poller(progress => {
|
||||||
let element: Element | undefined;
|
let element: Element | undefined;
|
||||||
let elements: Element[] = [];
|
let elements: Element[] = [];
|
||||||
if (querySelectorAll) {
|
if (querySelectorAll) {
|
||||||
|
|
@ -1301,7 +1301,7 @@ export class Frame extends SdkObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!element && !omitAttached)
|
if (!element && !omitAttached)
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
|
|
||||||
if (snapshotName) {
|
if (snapshotName) {
|
||||||
const previouslyMarkedElements = markedElements;
|
const previouslyMarkedElements = markedElements;
|
||||||
|
|
@ -1316,7 +1316,7 @@ export class Frame extends SdkObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback(progress, element, taskData as T, elements, continuePolling);
|
return callback(progress, element, taskData as T, elements);
|
||||||
});
|
});
|
||||||
}, { info, taskData, callbackText, querySelectorAll: options.querySelectorAll, logScale: options.logScale, omitAttached: options.omitAttached, snapshotName: progress.metadata.afterSnapshot });
|
}, { info, taskData, callbackText, querySelectorAll: options.querySelectorAll, logScale: options.logScale, omitAttached: options.omitAttached, snapshotName: progress.metadata.afterSnapshot });
|
||||||
}, true);
|
}, true);
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ import { CSSComplexSelectorList } from '../common/cssParser';
|
||||||
import { generateSelector } from './selectorGenerator';
|
import { generateSelector } from './selectorGenerator';
|
||||||
import type * as channels from '../../protocol/channels';
|
import type * as channels from '../../protocol/channels';
|
||||||
|
|
||||||
type Predicate<T> = (progress: InjectedScriptProgress, continuePolling: symbol) => T | symbol;
|
type Predicate<T> = (progress: InjectedScriptProgress) => T | symbol;
|
||||||
|
|
||||||
export type InjectedScriptProgress = {
|
export type InjectedScriptProgress = {
|
||||||
injectedScript: InjectedScript;
|
injectedScript: InjectedScript;
|
||||||
|
continuePolling: symbol;
|
||||||
aborted: boolean;
|
aborted: boolean;
|
||||||
log: (message: string) => void;
|
log: (message: string) => void;
|
||||||
logRepeating: (message: string) => void;
|
logRepeating: (message: string) => void;
|
||||||
|
|
@ -293,9 +294,8 @@ export class InjectedScript {
|
||||||
if (progress.aborted)
|
if (progress.aborted)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
const continuePolling = Symbol('continuePolling');
|
const success = predicate(progress);
|
||||||
const success = predicate(progress, continuePolling);
|
if (success !== progress.continuePolling)
|
||||||
if (success !== continuePolling)
|
|
||||||
fulfill(success as T);
|
fulfill(success as T);
|
||||||
else
|
else
|
||||||
scheduleNext(next);
|
scheduleNext(next);
|
||||||
|
|
@ -333,6 +333,7 @@ export class InjectedScript {
|
||||||
const progress: InjectedScriptProgress = {
|
const progress: InjectedScriptProgress = {
|
||||||
injectedScript: this,
|
injectedScript: this,
|
||||||
aborted: false,
|
aborted: false,
|
||||||
|
continuePolling: Symbol('continuePolling'),
|
||||||
log: (message: string) => {
|
log: (message: string) => {
|
||||||
lastMessage = message;
|
lastMessage = message;
|
||||||
unsentLog.push({ message });
|
unsentLog.push({ message });
|
||||||
|
|
@ -399,16 +400,16 @@ export class InjectedScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForElementStatesAndPerformAction<T>(node: Node, states: ElementState[], force: boolean | undefined,
|
waitForElementStatesAndPerformAction<T>(node: Node, states: ElementState[], force: boolean | undefined,
|
||||||
callback: (node: Node, progress: InjectedScriptProgress, continuePolling: symbol) => T | symbol): InjectedScriptPoll<T | 'error:notconnected'> {
|
callback: (node: Node, progress: InjectedScriptProgress) => T | symbol): InjectedScriptPoll<T | 'error:notconnected'> {
|
||||||
let lastRect: { x: number, y: number, width: number, height: number } | undefined;
|
let lastRect: { x: number, y: number, width: number, height: number } | undefined;
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
let samePositionCounter = 0;
|
let samePositionCounter = 0;
|
||||||
let lastTime = 0;
|
let lastTime = 0;
|
||||||
|
|
||||||
return this.pollRaf((progress, continuePolling) => {
|
return this.pollRaf(progress => {
|
||||||
if (force) {
|
if (force) {
|
||||||
progress.log(` forcing action`);
|
progress.log(` forcing action`);
|
||||||
return callback(node, progress, continuePolling);
|
return callback(node, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const state of states) {
|
for (const state of states) {
|
||||||
|
|
@ -418,7 +419,7 @@ export class InjectedScript {
|
||||||
return result;
|
return result;
|
||||||
if (!result) {
|
if (!result) {
|
||||||
progress.logRepeating(` element is not ${state} - waiting...`);
|
progress.logRepeating(` element is not ${state} - waiting...`);
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -431,12 +432,12 @@ export class InjectedScript {
|
||||||
// any client rect difference compared to synchronous call. We skip the synchronous call
|
// any client rect difference compared to synchronous call. We skip the synchronous call
|
||||||
// and only force layout during actual rafs as a small optimisation.
|
// and only force layout during actual rafs as a small optimisation.
|
||||||
if (++counter === 1)
|
if (++counter === 1)
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
|
|
||||||
// Drop frames that are shorter than 16ms - WebKit Win bug.
|
// Drop frames that are shorter than 16ms - WebKit Win bug.
|
||||||
const time = performance.now();
|
const time = performance.now();
|
||||||
if (this._stableRafCount > 1 && time - lastTime < 15)
|
if (this._stableRafCount > 1 && time - lastTime < 15)
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
lastTime = time;
|
lastTime = time;
|
||||||
|
|
||||||
const clientRect = element.getBoundingClientRect();
|
const clientRect = element.getBoundingClientRect();
|
||||||
|
|
@ -452,10 +453,10 @@ export class InjectedScript {
|
||||||
if (!isStableForLogs)
|
if (!isStableForLogs)
|
||||||
progress.logRepeating(` element is not stable - waiting...`);
|
progress.logRepeating(` element is not stable - waiting...`);
|
||||||
if (!isStable)
|
if (!isStable)
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback(node, progress, continuePolling);
|
return callback(node, progress);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,7 +496,7 @@ export class InjectedScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
selectOptions(optionsToSelect: (Node | { value?: string, label?: string, index?: number })[],
|
selectOptions(optionsToSelect: (Node | { value?: string, label?: string, index?: number })[],
|
||||||
node: Node, progress: InjectedScriptProgress, continuePolling: symbol): string[] | 'error:notconnected' | symbol {
|
node: Node, progress: InjectedScriptProgress): string[] | 'error:notconnected' | symbol {
|
||||||
const element = this.retarget(node, 'follow-label');
|
const element = this.retarget(node, 'follow-label');
|
||||||
if (!element)
|
if (!element)
|
||||||
return 'error:notconnected';
|
return 'error:notconnected';
|
||||||
|
|
@ -531,7 +532,7 @@ export class InjectedScript {
|
||||||
}
|
}
|
||||||
if (remainingOptionsToSelect.length) {
|
if (remainingOptionsToSelect.length) {
|
||||||
progress.logRepeating(' did not find some options - waiting... ');
|
progress.logRepeating(' did not find some options - waiting... ');
|
||||||
return continuePolling;
|
return progress.continuePolling;
|
||||||
}
|
}
|
||||||
select.value = undefined as any;
|
select.value = undefined as any;
|
||||||
selectedOptions.forEach(option => option.selected = true);
|
selectedOptions.forEach(option => option.selected = true);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue