From 2cf4caa4cfc406683a79a4662f488cad3e4bd9c9 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 24 Mar 2021 06:37:10 -0700 Subject: [PATCH] chore: implement mixins in protocol.yml (#5932) --- src/protocol/channels.ts | 16 +- src/protocol/protocol.yml | 296 ++++++++++++++----------------------- src/protocol/validator.ts | 10 +- utils/generate_channels.js | 33 +++-- 4 files changed, 143 insertions(+), 212 deletions(-) diff --git a/src/protocol/channels.ts b/src/protocol/channels.ts index dfdd7cc2bd..77d4700401 100644 --- a/src/protocol/channels.ts +++ b/src/protocol/channels.ts @@ -236,8 +236,8 @@ export type BrowserTypeLaunchParams = { password?: string, }, downloadsPath?: string, - firefoxUserPrefs?: any, chromiumSandbox?: boolean, + firefoxUserPrefs?: any, slowMo?: number, }; export type BrowserTypeLaunchOptions = { @@ -260,8 +260,8 @@ export type BrowserTypeLaunchOptions = { password?: string, }, downloadsPath?: string, - firefoxUserPrefs?: any, chromiumSandbox?: boolean, + firefoxUserPrefs?: any, slowMo?: number, }; export type BrowserTypeLaunchResult = { @@ -269,8 +269,6 @@ export type BrowserTypeLaunchResult = { }; export type BrowserTypeLaunchPersistentContextParams = { channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', - userDataDir: string, - sdkLanguage: string, executablePath?: string, args?: string[], ignoreAllDefaultArgs?: boolean, @@ -290,7 +288,7 @@ export type BrowserTypeLaunchPersistentContextParams = { }, downloadsPath?: string, chromiumSandbox?: boolean, - slowMo?: number, + sdkLanguage: string, noDefaultViewport?: boolean, viewport?: { width: number, @@ -317,7 +315,7 @@ export type BrowserTypeLaunchPersistentContextParams = { deviceScaleFactor?: number, isMobile?: boolean, hasTouch?: boolean, - colorScheme?: 'light' | 'dark' | 'no-preference', + colorScheme?: 'dark' | 'light' | 'no-preference', acceptDownloads?: boolean, _traceDir?: string, _debugName?: string, @@ -332,6 +330,8 @@ export type BrowserTypeLaunchPersistentContextParams = { omitContent?: boolean, path: string, }, + userDataDir: string, + slowMo?: number, }; export type BrowserTypeLaunchPersistentContextOptions = { channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', @@ -354,7 +354,6 @@ export type BrowserTypeLaunchPersistentContextOptions = { }, downloadsPath?: string, chromiumSandbox?: boolean, - slowMo?: number, noDefaultViewport?: boolean, viewport?: { width: number, @@ -381,7 +380,7 @@ export type BrowserTypeLaunchPersistentContextOptions = { deviceScaleFactor?: number, isMobile?: boolean, hasTouch?: boolean, - colorScheme?: 'light' | 'dark' | 'no-preference', + colorScheme?: 'dark' | 'light' | 'no-preference', acceptDownloads?: boolean, _traceDir?: string, _debugName?: string, @@ -396,6 +395,7 @@ export type BrowserTypeLaunchPersistentContextOptions = { omitContent?: boolean, path: string, }, + slowMo?: number, }; export type BrowserTypeLaunchPersistentContextResult = { context: BrowserContextChannel, diff --git a/src/protocol/protocol.yml b/src/protocol/protocol.yml index 022e586395..2dda2ec63a 100644 --- a/src/protocol/protocol.yml +++ b/src/protocol/protocol.yml @@ -223,6 +223,110 @@ SerializedError: value: SerializedValue? +LaunchOptions: + type: mixin + properties: + channel: + type: enum? + literals: + - chrome + - chrome-beta + - chrome-dev + - chrome-canary + - msedge + - msedge-beta + - msedge-dev + - msedge-canary + executablePath: string? + args: + type: array? + items: string + ignoreAllDefaultArgs: boolean? + ignoreDefaultArgs: + type: array? + items: string + handleSIGINT: boolean? + handleSIGTERM: boolean? + handleSIGHUP: boolean? + timeout: number? + env: + type: array? + items: NameValue + headless: boolean? + devtools: boolean? + proxy: + type: object? + properties: + server: string + bypass: string? + username: string? + password: string? + downloadsPath: string? + chromiumSandbox: boolean? + + +ContextOptions: + type: mixin + properties: + sdkLanguage: string + noDefaultViewport: boolean? + viewport: + type: object? + properties: + width: number + height: number + ignoreHTTPSErrors: boolean? + javaScriptEnabled: boolean? + bypassCSP: boolean? + userAgent: string? + locale: string? + timezoneId: string? + geolocation: + type: object? + properties: + longitude: number + latitude: number + accuracy: number? + permissions: + type: array? + items: string + extraHTTPHeaders: + type: array? + items: NameValue + offline: boolean? + httpCredentials: + type: object? + properties: + username: string + password: string + deviceScaleFactor: number? + isMobile: boolean? + hasTouch: boolean? + colorScheme: + type: enum? + literals: + - dark + - light + - no-preference + acceptDownloads: boolean? + _traceDir: string? + _debugName: string? + recordVideo: + type: object? + properties: + dir: string + size: + type: object? + properties: + width: number + height: number + recordHar: + type: object? + properties: + omitContent: boolean? + path: string + + Playwright: type: interface @@ -300,146 +404,18 @@ BrowserType: launch: parameters: - channel: - type: enum? - literals: - - chrome - - chrome-beta - - chrome-dev - - chrome-canary - - msedge - - msedge-beta - - msedge-dev - - msedge-canary - executablePath: string? - args: - type: array? - items: string - ignoreAllDefaultArgs: boolean? - ignoreDefaultArgs: - type: array? - items: string - handleSIGINT: boolean? - handleSIGTERM: boolean? - handleSIGHUP: boolean? - timeout: number? - env: - type: array? - items: NameValue - headless: boolean? - devtools: boolean? - proxy: - type: object? - properties: - server: string - bypass: string? - username: string? - password: string? - downloadsPath: string? + $mixin: LaunchOptions firefoxUserPrefs: json? - chromiumSandbox: boolean? slowMo: number? returns: browser: Browser launchPersistentContext: parameters: - channel: - type: enum? - literals: - - chrome - - chrome-beta - - chrome-dev - - chrome-canary - - msedge - - msedge-beta - - msedge-dev - - msedge-canary + $mixin1: LaunchOptions + $mixin2: ContextOptions userDataDir: string - sdkLanguage: string - executablePath: string? - args: - type: array? - items: string - ignoreAllDefaultArgs: boolean? - ignoreDefaultArgs: - type: array? - items: string - handleSIGINT: boolean? - handleSIGTERM: boolean? - handleSIGHUP: boolean? - timeout: number? - env: - type: array? - items: NameValue - headless: boolean? - devtools: boolean? - proxy: - type: object? - properties: - server: string - bypass: string? - username: string? - password: string? - downloadsPath: string? - chromiumSandbox: boolean? slowMo: number? - noDefaultViewport: boolean? - viewport: - type: object? - properties: - width: number - height: number - ignoreHTTPSErrors: boolean? - javaScriptEnabled: boolean? - bypassCSP: boolean? - userAgent: string? - locale: string? - timezoneId: string? - geolocation: - type: object? - properties: - longitude: number - latitude: number - accuracy: number? - permissions: - type: array? - items: string - extraHTTPHeaders: - type: array? - items: NameValue - offline: boolean? - httpCredentials: - type: object? - properties: - username: string - password: string - deviceScaleFactor: number? - isMobile: boolean? - hasTouch: boolean? - colorScheme: - type: enum? - literals: - - light - - dark - - no-preference - acceptDownloads: boolean? - _traceDir: string? - _debugName: string? - recordVideo: - type: object? - properties: - dir: string - size: - type: object? - properties: - width: number - height: number - recordHar: - type: object? - properties: - omitContent: boolean? - path: string returns: context: BrowserContext @@ -466,63 +442,7 @@ Browser: newContext: parameters: - sdkLanguage: string - noDefaultViewport: boolean? - viewport: - type: object? - properties: - width: number - height: number - ignoreHTTPSErrors: boolean? - javaScriptEnabled: boolean? - bypassCSP: boolean? - userAgent: string? - locale: string? - timezoneId: string? - geolocation: - type: object? - properties: - longitude: number - latitude: number - accuracy: number? - permissions: - type: array? - items: string - extraHTTPHeaders: - type: array? - items: NameValue - offline: boolean? - httpCredentials: - type: object? - properties: - username: string - password: string - deviceScaleFactor: number? - isMobile: boolean? - hasTouch: boolean? - colorScheme: - type: enum? - literals: - - dark - - light - - no-preference - acceptDownloads: boolean? - _traceDir: string? - _debugName: string? - recordVideo: - type: object? - properties: - dir: string - size: - type: object? - properties: - width: number - height: number - recordHar: - type: object? - properties: - omitContent: boolean? - path: string + $mixin: ContextOptions proxy: type: object? properties: diff --git a/src/protocol/validator.ts b/src/protocol/validator.ts index f45740d441..8fe920772c 100644 --- a/src/protocol/validator.ts +++ b/src/protocol/validator.ts @@ -173,14 +173,12 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { password: tOptional(tString), })), downloadsPath: tOptional(tString), - firefoxUserPrefs: tOptional(tAny), chromiumSandbox: tOptional(tBoolean), + firefoxUserPrefs: tOptional(tAny), slowMo: tOptional(tNumber), }); scheme.BrowserTypeLaunchPersistentContextParams = tObject({ channel: tOptional(tEnum(['chrome', 'chrome-beta', 'chrome-dev', 'chrome-canary', 'msedge', 'msedge-beta', 'msedge-dev', 'msedge-canary'])), - userDataDir: tString, - sdkLanguage: tString, executablePath: tOptional(tString), args: tOptional(tArray(tString)), ignoreAllDefaultArgs: tOptional(tBoolean), @@ -200,7 +198,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { })), downloadsPath: tOptional(tString), chromiumSandbox: tOptional(tBoolean), - slowMo: tOptional(tNumber), + sdkLanguage: tString, noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tNumber, @@ -227,7 +225,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { deviceScaleFactor: tOptional(tNumber), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), - colorScheme: tOptional(tEnum(['light', 'dark', 'no-preference'])), + colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference'])), acceptDownloads: tOptional(tBoolean), _traceDir: tOptional(tString), _debugName: tOptional(tString), @@ -242,6 +240,8 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { omitContent: tOptional(tBoolean), path: tString, })), + userDataDir: tString, + slowMo: tOptional(tNumber), }); scheme.BrowserTypeConnectOverCDPParams = tObject({ sdkLanguage: tString, diff --git a/utils/generate_channels.js b/utils/generate_channels.js index ab6703ff28..134aae7966 100755 --- a/utils/generate_channels.js +++ b/utils/generate_channels.js @@ -21,6 +21,8 @@ const path = require('path'); const yaml = require('yaml'); const channels = new Set(); +const inherits = new Map(); +const mixins = new Map(); function raise(item) { throw new Error('Invalid item: ' + JSON.stringify(item, null, 2)); @@ -73,17 +75,24 @@ function inlineType(type, indent, wrapEnums = false) { raise(type); } -function properties(props, indent, onlyOptional) { +function properties(properties, indent, onlyOptional) { const ts = []; const scheme = []; - for (const [name, value] of Object.entries(props)) { - const inner = inlineType(value, indent); - if (onlyOptional && !inner.optional) - continue; - ts.push(`${indent}${name}${inner.optional ? '?' : ''}: ${inner.ts},`); - const wrapped = inner.optional ? `tOptional(${inner.scheme})` : inner.scheme; - scheme.push(`${indent}${name}: ${wrapped},`); - } + const visitProperties = props => { + for (const [name, value] of Object.entries(props)) { + if (name.startsWith('$mixin')) { + visitProperties(mixins.get(value).properties); + continue; + } + const inner = inlineType(value, indent); + if (onlyOptional && !inner.optional) + continue; + ts.push(`${indent}${name}${inner.optional ? '?' : ''}: ${inner.ts},`); + const wrapped = inner.optional ? `tOptional(${inner.scheme})` : inner.scheme; + scheme.push(`${indent}${name}: ${wrapped},`); + } + }; + visitProperties(properties); return { ts: ts.join('\n'), scheme: scheme.join('\n') }; } @@ -166,13 +175,14 @@ function addScheme(name, s) { validator_ts.push(...lines.map(line => ' ' + line)); } -const inherits = new Map(); for (const [name, value] of Object.entries(protocol)) { if (value.type === 'interface') { channels.add(name); if (value.extends) inherits.set(name, value.extends); } + if (value.type === 'mixin') + mixins.set(name, value); } for (const [name, item] of Object.entries(protocol)) { @@ -219,12 +229,13 @@ for (const [name, item] of Object.entries(protocol)) { channels_ts.push(`}`); for (const [typeName, typeValue] of ts_types) channels_ts.push(`export type ${typeName} = ${typeValue};`); + channels_ts.push(``); } else if (item.type === 'object') { const inner = objectType(item.properties, ''); channels_ts.push(`export type ${name} = ${inner.ts};`); + channels_ts.push(``); addScheme(name, inner.scheme); } - channels_ts.push(``); } validator_ts.push(`