chore: remove injected -> types dependency (#3606)

This way, injected is self-contained and we can ensure it does not
depend on anything node-specific.
This commit is contained in:
Dmitry Gozman 2020-08-24 15:30:45 -07:00 коммит произвёл GitHub
Родитель 3bdf0e804a
Коммит bdbcae16cb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 40 добавлений и 42 удалений

Просмотреть файл

@ -16,7 +16,7 @@
import * as frames from './frames';
import { assert } from '../utils/utils';
import type InjectedScript from './injected/injectedScript';
import type { InjectedScript, InjectedScriptPoll } from './injected/injectedScript';
import * as injectedScriptSource from '../generated/injectedScriptSource';
import * as debugScriptSource from '../generated/debugScriptSource';
import * as js from './javascript';
@ -718,9 +718,9 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
// - cancels the poll when progress cancels.
export class InjectedScriptPollHandler<T> {
private _progress: Progress;
private _poll: js.JSHandle<types.InjectedScriptPoll<T>> | null;
private _poll: js.JSHandle<InjectedScriptPoll<T>> | null;
constructor(progress: Progress, poll: js.JSHandle<types.InjectedScriptPoll<T>>) {
constructor(progress: Progress, poll: js.JSHandle<InjectedScriptPoll<T>>) {
this._progress = progress;
this._poll = poll;
// Ensure we cancel the poll before progress aborts and returns:
@ -836,7 +836,7 @@ function compensateHalfIntegerRoundingError(point: types.Point) {
point.y -= 0.02;
}
export type SchedulableTask<T> = (injectedScript: js.JSHandle<InjectedScript>) => Promise<js.JSHandle<types.InjectedScriptPoll<T>>>;
export type SchedulableTask<T> = (injectedScript: js.JSHandle<InjectedScript>) => Promise<js.JSHandle<InjectedScriptPoll<T>>>;
export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' | 'detached' | 'visible' | 'hidden', root?: ElementHandle): SchedulableTask<Element | undefined> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, state, root }) => {

Просмотреть файл

@ -14,7 +14,6 @@
* limitations under the License.
*/
import type * as types from '../types';
import { createAttributeEngine } from './attributeSelectorEngine';
import { createCSSEngine } from './cssSelectorEngine';
import { SelectorEngine, SelectorRoot } from './selectorEngine';
@ -23,9 +22,24 @@ import { XPathEngine } from './xpathSelectorEngine';
import { ParsedSelector } from '../common/selectorParser';
import { FatalDOMError } from '../common/domErrors';
type Predicate<T> = (progress: types.InjectedScriptProgress, continuePolling: symbol) => T | symbol;
type Predicate<T> = (progress: InjectedScriptProgress, continuePolling: symbol) => T | symbol;
export default class InjectedScript {
export type InjectedScriptProgress = {
aborted: boolean,
log: (message: string) => void,
logRepeating: (message: string) => void,
};
export type InjectedScriptPoll<T> = {
result: Promise<T>,
// Takes more logs, waiting until at least one message is available.
takeNextLogs: () => Promise<string[]>,
// Takes all current logs without waiting.
takeLastLogs: () => string[],
cancel: () => void,
};
export class InjectedScript {
readonly engines: Map<string, SelectorEngine>;
constructor(customEngines: { name: string, engine: SelectorEngine}[]) {
@ -105,7 +119,7 @@ export default class InjectedScript {
return rect.width > 0 && rect.height > 0;
}
pollRaf<T>(predicate: Predicate<T>): types.InjectedScriptPoll<T> {
pollRaf<T>(predicate: Predicate<T>): InjectedScriptPoll<T> {
return this._runAbortableTask(progress => {
let fulfill: (result: T) => void;
let reject: (error: Error) => void;
@ -131,7 +145,7 @@ export default class InjectedScript {
});
}
pollInterval<T>(pollInterval: number, predicate: Predicate<T>): types.InjectedScriptPoll<T> {
pollInterval<T>(pollInterval: number, predicate: Predicate<T>): InjectedScriptPoll<T> {
return this._runAbortableTask(progress => {
let fulfill: (result: T) => void;
let reject: (error: Error) => void;
@ -157,7 +171,7 @@ export default class InjectedScript {
});
}
private _runAbortableTask<T>(task: (progess: types.InjectedScriptProgress) => Promise<T>): types.InjectedScriptPoll<T> {
private _runAbortableTask<T>(task: (progess: InjectedScriptProgress) => Promise<T>): InjectedScriptPoll<T> {
let unsentLogs: string[] = [];
let takeNextLogsCallback: ((logs: string[]) => void) | undefined;
const logReady = () => {
@ -175,7 +189,7 @@ export default class InjectedScript {
});
let lastLog = '';
const progress: types.InjectedScriptProgress = {
const progress: InjectedScriptProgress = {
aborted: false,
log: (message: string) => {
lastLog = message;
@ -203,7 +217,7 @@ export default class InjectedScript {
return { left: parseInt(style.borderLeftWidth || '', 10), top: parseInt(style.borderTopWidth || '', 10) };
}
selectOptions(node: Node, optionsToSelect: (Node | types.SelectOption)[]): string[] | 'error:notconnected' | FatalDOMError {
selectOptions(node: Node, optionsToSelect: (Node | { value?: string, label?: string, index?: number })[]): string[] | 'error:notconnected' | FatalDOMError {
if (node.nodeName.toLowerCase() !== 'select')
return 'error:notselect';
if (!node.isConnected)
@ -234,7 +248,7 @@ export default class InjectedScript {
return options.filter(option => option.selected).map(option => option.value);
}
waitForEnabledAndFill(node: Node, value: string): types.InjectedScriptPoll<FatalDOMError | 'error:notconnected' | 'needsinput' | 'done'> {
waitForEnabledAndFill(node: Node, value: string): InjectedScriptPoll<FatalDOMError | 'error:notconnected' | 'needsinput' | 'done'> {
return this.pollRaf((progress, continuePolling) => {
if (node.nodeType !== Node.ELEMENT_NODE)
return 'error:notelement';
@ -299,7 +313,7 @@ export default class InjectedScript {
});
}
waitForVisibleAndSelectText(node: Node): types.InjectedScriptPoll<FatalDOMError | 'error:notconnected' | 'done'> {
waitForVisibleAndSelectText(node: Node): InjectedScriptPoll<FatalDOMError | 'error:notconnected' | 'done'> {
return this.pollRaf((progress, continuePolling) => {
if (node.nodeType !== Node.ELEMENT_NODE)
return 'error:notelement';
@ -344,7 +358,7 @@ export default class InjectedScript {
return 'done';
}
waitForNodeVisible(node: Node): types.InjectedScriptPoll<'error:notconnected' | 'done'> {
waitForNodeVisible(node: Node): InjectedScriptPoll<'error:notconnected' | 'done'> {
return this.pollRaf((progress, continuePolling) => {
const element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement;
if (!node.isConnected || !element)
@ -357,7 +371,7 @@ export default class InjectedScript {
});
}
waitForNodeHidden(node: Node): types.InjectedScriptPoll<'done'> {
waitForNodeHidden(node: Node): InjectedScriptPoll<'done'> {
return this.pollRaf((progress, continuePolling) => {
const element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement;
if (!node.isConnected || !element)
@ -370,7 +384,7 @@ export default class InjectedScript {
});
}
waitForNodeEnabled(node: Node): types.InjectedScriptPoll<'error:notconnected' | 'done'> {
waitForNodeEnabled(node: Node): InjectedScriptPoll<'error:notconnected' | 'done'> {
return this.pollRaf((progress, continuePolling) => {
const element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement;
if (!node.isConnected || !element)
@ -383,7 +397,7 @@ export default class InjectedScript {
});
}
waitForNodeDisabled(node: Node): types.InjectedScriptPoll<'error:notconnected' | 'done'> {
waitForNodeDisabled(node: Node): InjectedScriptPoll<'error:notconnected' | 'done'> {
return this.pollRaf((progress, continuePolling) => {
const element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement;
if (!node.isConnected || !element)
@ -438,7 +452,7 @@ export default class InjectedScript {
throw new Error('Not a checkbox');
}
async setInputFiles(node: Node, payloads: types.FilePayload[]) {
async setInputFiles(node: Node, payloads: { name: string, mimeType: string, buffer: string }[]) {
if (node.nodeType !== Node.ELEMENT_NODE)
return 'Node is not of type HTMLElement';
const element: Element | undefined = node as Element;
@ -461,8 +475,8 @@ export default class InjectedScript {
input.dispatchEvent(new Event('change', { 'bubbles': true }));
}
waitForDisplayedAtStablePosition(node: Node, rafCount: number, waitForEnabled: boolean): types.InjectedScriptPoll<'error:notconnected' | 'done'> {
let lastRect: types.Rect | undefined;
waitForDisplayedAtStablePosition(node: Node, rafCount: number, waitForEnabled: boolean): InjectedScriptPoll<'error:notconnected' | 'done'> {
let lastRect: { x: number, y: number, width: number, height: number } | undefined;
let counter = 0;
let samePositionCounter = 0;
let lastTime = 0;
@ -517,7 +531,7 @@ export default class InjectedScript {
});
}
checkHitTargetAt(node: Node, point: types.Point): 'error:notconnected' | 'done' | { hitTargetDescription: string } {
checkHitTargetAt(node: Node, point: { x: number, y: number }): 'error:notconnected' | 'done' | { hitTargetDescription: string } {
let element: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement;
if (!element || !element.isConnected)
return 'error:notconnected';
@ -683,3 +697,5 @@ const eventType = new Map<string, 'mouse'|'keyboard'|'touch'|'pointer'|'focus'|'
['dragexit', 'drag'],
['drop', 'drag'],
]);
export default InjectedScript;

Просмотреть файл

@ -15,8 +15,6 @@
* limitations under the License.
*/
// NOTE: No imports allowed - only primitive, self-contained types are allowed here.
export type Size = { width: number, height: number };
export type Point = { x: number, y: number };
export type Rect = Size & Point;
@ -158,21 +156,6 @@ export type JSCoverageEntry = {
}[]
};
export type InjectedScriptProgress = {
aborted: boolean,
log: (message: string) => void,
logRepeating: (message: string) => void,
};
export type InjectedScriptPoll<T> = {
result: Promise<T>,
// Takes more logs, waiting until at least one message is available.
takeNextLogs: () => Promise<string[]>,
// Takes all current logs without waiting.
takeLastLogs: () => string[],
cancel: () => void,
};
export type ProxySettings = {
server: string,
bypass?: string,

Просмотреть файл

@ -108,11 +108,10 @@ DEPS['src/server/'] = [
// No dependencies for code shared between node and page.
DEPS['src/server/common/'] = [];
// Strict dependencies for injected code.
// TODO: remove the injected->types dependency.
DEPS['src/server/injected/'] = ['src/server/common/', 'src/server/types.ts'];
DEPS['src/server/injected/'] = ['src/server/common/'];
// Electron uses chromium internally.
DEPS['src/server/electron/'] = [...DEPS['src/server/'], 'src/server/chromium/'];
DEPS['src/server/playwright.ts'] = [...DEPS['src/server/'], 'src/server/chromium/', 'src/server/webkit/', 'src/server/firefox/'];