chore: make NodeSnapshot type recursive and more (#30619)

Also, deviceDescriptors are now imported with ESM import instead of require()
This commit is contained in:
Rui Figueira 2024-05-08 18:08:40 +00:00 committed by GitHub
parent 4b5ecd2d79
commit cf3ff6531a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 44 additions and 33 deletions

View File

@ -15,7 +15,8 @@
* limitations under the License.
*/
/**
* @type {import('./types').Devices}
*/
module.exports = require("./deviceDescriptorsSource.json")
import type { Devices } from './types';
import deviceDescriptorsSource from './deviceDescriptorsSource.json';
export const deviceDescriptors = deviceDescriptorsSource as Devices;

View File

@ -26,7 +26,7 @@ import { Dispatcher } from './dispatcher';
import { yazl, yauzl } from '../../zipBundle';
import { ZipFile } from '../../utils/zipFile';
import type * as har from '@trace/har';
import type { HeadersArray, Devices } from '../types';
import type { HeadersArray } from '../types';
import { JsonPipeDispatcher } from '../dispatchers/jsonPipeDispatcher';
import { WebSocketTransport } from '../transport';
import { SocksInterceptor } from '../socksInterceptor';
@ -40,6 +40,7 @@ import type http from 'http';
import type { Playwright } from '../playwright';
import { SdkObject } from '../../server/instrumentation';
import { serializeClientSideCallMetadata } from '../../utils';
import { deviceDescriptors as descriptors } from '../deviceDescriptors';
export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.LocalUtilsChannel, RootDispatcher> implements channels.LocalUtilsChannel {
_type_LocalUtils: boolean;
@ -53,7 +54,6 @@ export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.
constructor(scope: RootDispatcher, playwright: Playwright) {
const localUtils = new SdkObject(playwright, 'localUtils', 'localUtils');
const descriptors = require('../deviceDescriptors') as Devices;
const deviceDescriptors = Object.entries(descriptors)
.map(([name, descriptor]) => ({ name, descriptor }));
super(scope, localUtils, 'LocalUtils', {

View File

@ -22,7 +22,7 @@ import type { Action } from './recorderActions';
import type { MouseClickOptions } from './utils';
import { toModifiers } from './utils';
import { escapeWithQuotes } from '../../utils/isomorphic/stringUtils';
const deviceDescriptors = require('../deviceDescriptorsSource.json');
import { deviceDescriptors } from '../deviceDescriptors';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';
type CSharpLanguageMode = 'library' | 'mstest' | 'nunit';

View File

@ -21,7 +21,7 @@ import type { ActionInContext } from './codeGenerator';
import type { Action } from './recorderActions';
import type { MouseClickOptions } from './utils';
import { toModifiers } from './utils';
const deviceDescriptors = require('../deviceDescriptorsSource.json');
import { deviceDescriptors } from '../deviceDescriptors';
import { JavaScriptFormatter } from './javascript';
import { escapeWithQuotes } from '../../utils/isomorphic/stringUtils';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';

View File

@ -21,7 +21,7 @@ import type { ActionInContext } from './codeGenerator';
import type { Action } from './recorderActions';
import type { MouseClickOptions } from './utils';
import { toModifiers } from './utils';
const deviceDescriptors = require('../deviceDescriptorsSource.json');
import { deviceDescriptors } from '../deviceDescriptors';
import { escapeWithQuotes } from '../../utils/isomorphic/stringUtils';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';

View File

@ -22,7 +22,7 @@ import type { Action } from './recorderActions';
import type { MouseClickOptions } from './utils';
import { toModifiers } from './utils';
import { escapeWithQuotes, toSnakeCase } from '../../utils/isomorphic/stringUtils';
const deviceDescriptors = require('../deviceDescriptorsSource.json');
import { deviceDescriptors } from '../deviceDescriptors';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';
export class PythonLanguageGenerator implements LanguageGenerator {

View File

@ -540,7 +540,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
return checkAndReturn(result);
};
const visitStyleSheet = (sheet: CSSStyleSheet) => {
const visitStyleSheet = (sheet: CSSStyleSheet): { equals: boolean, n: NodeSnapshot } => {
const data = ensureCachedData(sheet);
const oldCSSText = data.cssText;
const cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet, true /* forceText */)!;

View File

@ -14,7 +14,15 @@
* limitations under the License.
*/
import type { FrameSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot } from '@trace/snapshot';
import type { FrameSnapshot, NodeNameAttributesChildNodesSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot, SubtreeReferenceSnapshot } from '@trace/snapshot';
function isNodeNameAttributesChildNodesSnapshot(n: NodeSnapshot): n is NodeNameAttributesChildNodesSnapshot {
return Array.isArray(n) && typeof n[0] === 'string';
}
function isSubtreeReferenceSnapshot(n: NodeSnapshot): n is SubtreeReferenceSnapshot {
return Array.isArray(n) && Array.isArray(n[0]);
}
export class SnapshotRenderer {
private _snapshots: FrameSnapshot[];
@ -54,7 +62,7 @@ export class SnapshotRenderer {
}
if (!(n as any)._string) {
if (Array.isArray(n[0])) {
if (isSubtreeReferenceSnapshot(n)) {
// Node reference.
const referenceIndex = snapshotIndex - n[0][0];
if (referenceIndex >= 0 && referenceIndex <= snapshotIndex) {
@ -63,12 +71,13 @@ export class SnapshotRenderer {
if (nodeIndex >= 0 && nodeIndex < nodes.length)
(n as any)._string = visit(nodes[nodeIndex], referenceIndex, parentTag, parentAttrs);
}
} else if (typeof n[0] === 'string') {
} else if (isNodeNameAttributesChildNodesSnapshot(n)) {
const [name, nodeAttrs, ...children] = n;
// Element node.
// Note that <noscript> will not be rendered by default in the trace viewer, because
// JS is enabled. So rename it to <x-noscript>.
const nodeName = n[0] === 'NOSCRIPT' ? 'X-NOSCRIPT' : n[0];
const attrs = Object.entries(n[1] || {});
const nodeName = name === 'NOSCRIPT' ? 'X-NOSCRIPT' : name;
const attrs = Object.entries(nodeAttrs || {});
const builder: string[] = [];
builder.push('<', nodeName);
const kCurrentSrcAttribute = '__playwright_current_src__';
@ -101,8 +110,8 @@ export class SnapshotRenderer {
builder.push(' ', attrName, '="', escapeAttribute(attrValue), '"');
}
builder.push('>');
for (let i = 2; i < n.length; i++)
builder.push(visit(n[i], snapshotIndex, nodeName, attrs));
for (const child of children)
builder.push(visit(child, snapshotIndex, nodeName, attrs));
if (!autoClosing.has(nodeName))
builder.push('</', nodeName, '>');
(n as any)._string = builder.join('');
@ -200,9 +209,10 @@ function snapshotNodes(snapshot: FrameSnapshot): NodeSnapshot[] {
const visit = (n: NodeSnapshot) => {
if (typeof n === 'string') {
nodes.push(n);
} else if (typeof n[0] === 'string') {
for (let i = 2; i < n.length; i++)
visit(n[i]);
} else if (isNodeNameAttributesChildNodesSnapshot(n)) {
const [,, ...children] = n;
for (const child of children)
visit(child);
nodes.push(n);
}
};

View File

@ -18,18 +18,18 @@ import type { Entry as HAREntry } from './har';
export type ResourceSnapshot = HAREntry;
export type NodeSnapshot =
// Text node.
string |
// Subtree reference, "x snapshots ago, node #y". Could point to a text node.
// Only nodes that are not references are counted, starting from zero, using post-order traversal.
[ [number, number] ] |
// Just node name.
[ string ] |
// Node name, attributes, child nodes.
// Unfortunately, we cannot make this type definition recursive, therefore "any".
[ string, { [attr: string]: string }, ...any ];
// Text node.
export type TextNodeSnapshot = string;
// Subtree reference, "x snapshots ago, node #y". Could point to a text node.
// Only nodes that are not references are counted, starting from zero, using post-order traversal.
export type SubtreeReferenceSnapshot = [ [number, number] ];
// Node name, and optional attributes and child nodes.
export type NodeNameAttributesChildNodesSnapshot = [ string ] | [ string, Record<string, string>, ...NodeSnapshot[] ];
export type NodeSnapshot =
TextNodeSnapshot |
SubtreeReferenceSnapshot |
NodeNameAttributesChildNodesSnapshot;
export type ResourceOverride = {
url: string,

View File

@ -16,7 +16,7 @@
// @ts-check
const path = require('path');
const devices = require('../../packages/playwright-core/lib/server/deviceDescriptors');
const devices = require('../../packages/playwright-core/lib/server/deviceDescriptorsSource.json');
const md = require('../markdown');
const docs = require('../doclint/documentation');
const PROJECT_DIR = path.join(__dirname, '..', '..');