From e697b1a6636faac5bf98ed8798a070565b1d94dd Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 12 Feb 2025 18:03:23 -0800 Subject: [PATCH 01/13] chore: remove stackTrace => path dependency (#34763) --- .../playwright-core/ThirdPartyNotices.txt | 33 +---- .../bundles/utils/package-lock.json | 9 -- .../bundles/utils/package.json | 1 - .../bundles/utils/src/utilsBundleImpl.ts | 3 - .../playwright-core/src/browserServerImpl.ts | 2 +- .../src/client/browserContext.ts | 2 +- .../src/client/channelOwner.ts | 4 +- .../playwright-core/src/client/connection.ts | 2 +- .../playwright-core/src/client/network.ts | 2 +- packages/playwright-core/src/client/waiter.ts | 2 +- .../playwright-core/src/inProcessFactory.ts | 4 + .../src/server/chromium/crExecutionContext.ts | 2 +- .../src/server/chromium/crPage.ts | 2 +- .../src/server/chromium/crProtocolHelper.ts | 2 +- .../src/server/firefox/ffExecutionContext.ts | 2 +- .../src/server/firefox/ffPage.ts | 2 +- .../src/server/protocolError.ts | 2 +- .../src/server/registry/browserFetcher.ts | 3 +- .../src/server/utils/comparators.ts | 3 +- .../src/server/webkit/wkPage.ts | 2 +- packages/playwright-core/src/utils.ts | 3 +- .../src/utils/isomorphic/colors.ts | 117 ++++++++++++++++++ .../src/utils/{ => isomorphic}/stackTrace.ts | 36 +++--- .../src/utils/{ => isomorphic}/stackUtils.ts | 21 +++- .../playwright-core/src/utils/platform.ts | 5 + packages/playwright-core/src/utilsBundle.ts | 1 - .../playwright/src/matchers/matcherHint.ts | 2 +- packages/playwright/src/matchers/matchers.ts | 2 +- packages/playwright/src/matchers/toHaveURL.ts | 2 +- .../src/matchers/toMatchSnapshot.ts | 2 +- .../playwright/src/matchers/toMatchText.ts | 2 +- .../playwright/src/plugins/webServerPlugin.ts | 3 +- packages/playwright/src/reporters/base.ts | 47 +------ packages/playwright/src/reporters/github.ts | 3 +- packages/playwright/src/reporters/html.ts | 3 +- packages/playwright/src/runner/dispatcher.ts | 2 +- packages/playwright/src/runner/rebase.ts | 3 +- packages/playwright/src/runner/taskRunner.ts | 3 +- packages/playwright/src/runner/watchMode.ts | 2 +- packages/playwright/src/util.ts | 2 +- .../playwright/src/worker/timeoutManager.ts | 2 +- packages/playwright/src/worker/workerMain.ts | 2 +- 42 files changed, 201 insertions(+), 148 deletions(-) create mode 100644 packages/playwright-core/src/utils/isomorphic/colors.ts rename packages/playwright-core/src/utils/{ => isomorphic}/stackTrace.ts (84%) rename packages/playwright-core/src/utils/{ => isomorphic}/stackUtils.ts (88%) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 420d698fa5..f9d2225d75 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -11,7 +11,6 @@ This project incorporates components from the projects listed below. The origina - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) - codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) -- colors@1.4.0 (https://github.com/Marak/colors.js) - commander@8.3.0 (https://github.com/tj/commander.js) - concat-map@0.0.1 (https://github.com/substack/node-concat-map) - debug@4.3.4 (https://github.com/debug-js/debug) @@ -355,36 +354,6 @@ THE SOFTWARE. ========================================= END OF codemirror@5.65.18 AND INFORMATION -%% colors@1.4.0 NOTICES AND INFORMATION BEGIN HERE -========================================= -MIT License - -Original Library - - Copyright (c) Marak Squires - -Additional Functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -========================================= -END OF colors@1.4.0 AND INFORMATION - %% commander@8.3.0 NOTICES AND INFORMATION BEGIN HERE ========================================= (The MIT License) @@ -1555,6 +1524,6 @@ END OF yazl@2.5.1 AND INFORMATION SUMMARY BEGIN HERE ========================================= -Total Packages: 46 +Total Packages: 45 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index 49e99ef5c3..a70731aa0e 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -8,7 +8,6 @@ "name": "utils-bundle", "version": "0.0.1", "dependencies": { - "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", "diff": "^7.0.0", @@ -163,14 +162,6 @@ "concat-map": "0.0.1" } }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index e7f09cf3a0..76f6a4986a 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -9,7 +9,6 @@ "generate-license": "node ../../../../utils/generate_third_party_notice.js" }, "dependencies": { - "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", "diff": "^7.0.0", diff --git a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts index 409372e894..284ca5e7ad 100644 --- a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts @@ -16,9 +16,6 @@ /* eslint-disable import/order */ -import colorsLibrary from 'colors/safe'; -export const colors = colorsLibrary; - import debugLibrary from 'debug'; export const debug = debugLibrary; diff --git a/packages/playwright-core/src/browserServerImpl.ts b/packages/playwright-core/src/browserServerImpl.ts index e8d66bc4c4..77fb9a9844 100644 --- a/packages/playwright-core/src/browserServerImpl.ts +++ b/packages/playwright-core/src/browserServerImpl.ts @@ -21,7 +21,7 @@ import { helper } from './server/helper'; import { serverSideCallMetadata } from './server/instrumentation'; import { createPlaywright } from './server/playwright'; import { createGuid } from './server/utils/crypto'; -import { rewriteErrorMessage } from './utils/stackTrace'; +import { rewriteErrorMessage } from './utils/isomorphic/stackTrace'; import { ws } from './utilsBundle'; import type { BrowserServer, BrowserServerLauncher } from './client/browserType'; diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index 7c0210ceaf..32cac6ba7f 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -39,7 +39,7 @@ import { mkdirIfNeeded } from '../utils/fileUtils'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { urlMatchesEqual } from '../utils/isomorphic/urlMatch'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; -import { rewriteErrorMessage } from '../utils/stackTrace'; +import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace'; import type { BrowserType } from './browserType'; import type { BrowserContextOptions, Headers, LaunchOptions, StorageState, WaitForEventOptions } from './types'; diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 70a5c51777..5c5afcdc2d 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -18,7 +18,7 @@ import { EventEmitter } from './eventEmitter'; import { ValidationError, maybeFindValidator } from '../protocol/validator'; import { isUnderTest } from '../utils/debug'; import { debugLogger } from '../utils/debugLogger'; -import { captureLibraryStackTrace, stringifyStackFrames } from '../utils/stackTrace'; +import { captureLibraryStackTrace, stringifyStackFrames } from '../utils/isomorphic/stackTrace'; import { zones } from '../utils/zones'; import type { ClientInstrumentation } from './clientInstrumentation'; @@ -183,7 +183,7 @@ export abstract class ChannelOwner applyStyle(0, 0, text), + + bold: (text: string) => applyStyle(1, 22, text), + dim: (text: string) => applyStyle(2, 22, text), + italic: (text: string) => applyStyle(3, 23, text), + underline: (text: string) => applyStyle(4, 24, text), + inverse: (text: string) => applyStyle(7, 27, text), + hidden: (text: string) => applyStyle(8, 28, text), + strikethrough: (text: string) => applyStyle(9, 29, text), + + black: (text: string) => applyStyle(30, 39, text), + red: (text: string) => applyStyle(31, 39, text), + green: (text: string) => applyStyle(32, 39, text), + yellow: (text: string) => applyStyle(33, 39, text), + blue: (text: string) => applyStyle(34, 39, text), + magenta: (text: string) => applyStyle(35, 39, text), + cyan: (text: string) => applyStyle(36, 39, text), + white: (text: string) => applyStyle(37, 39, text), + gray: (text: string) => applyStyle(90, 39, text), + grey: (text: string) => applyStyle(90, 39, text), + + brightRed: (text: string) => applyStyle(91, 39, text), + brightGreen: (text: string) => applyStyle(92, 39, text), + brightYellow: (text: string) => applyStyle(93, 39, text), + brightBlue: (text: string) => applyStyle(94, 39, text), + brightMagenta: (text: string) => applyStyle(95, 39, text), + brightCyan: (text: string) => applyStyle(96, 39, text), + brightWhite: (text: string) => applyStyle(97, 39, text), + + bgBlack: (text: string) => applyStyle(40, 49, text), + bgRed: (text: string) => applyStyle(41, 49, text), + bgGreen: (text: string) => applyStyle(42, 49, text), + bgYellow: (text: string) => applyStyle(43, 49, text), + bgBlue: (text: string) => applyStyle(44, 49, text), + bgMagenta: (text: string) => applyStyle(45, 49, text), + bgCyan: (text: string) => applyStyle(46, 49, text), + bgWhite: (text: string) => applyStyle(47, 49, text), + bgGray: (text: string) => applyStyle(100, 49, text), + bgGrey: (text: string) => applyStyle(100, 49, text), + + bgBrightRed: (text: string) => applyStyle(101, 49, text), + bgBrightGreen: (text: string) => applyStyle(102, 49, text), + bgBrightYellow: (text: string) => applyStyle(103, 49, text), + bgBrightBlue: (text: string) => applyStyle(104, 49, text), + bgBrightMagenta: (text: string) => applyStyle(105, 49, text), + bgBrightCyan: (text: string) => applyStyle(106, 49, text), + bgBrightWhite: (text: string) => applyStyle(107, 49, text), +}; + +type Colors = typeof colors; + +export const noColors: Colors = { + enabled: false, + reset: t => t, + bold: t => t, + dim: t => t, + italic: t => t, + underline: t => t, + inverse: t => t, + hidden: t => t, + strikethrough: t => t, + black: t => t, + red: t => t, + green: t => t, + yellow: t => t, + blue: t => t, + magenta: t => t, + cyan: t => t, + white: t => t, + gray: t => t, + grey: t => t, + brightRed: t => t, + brightGreen: t => t, + brightYellow: t => t, + brightBlue: t => t, + brightMagenta: t => t, + brightCyan: t => t, + brightWhite: t => t, + bgBlack: t => t, + bgRed: t => t, + bgGreen: t => t, + bgYellow: t => t, + bgBlue: t => t, + bgMagenta: t => t, + bgCyan: t => t, + bgWhite: t => t, + bgGray: t => t, + bgGrey: t => t, + bgBrightRed: t => t, + bgBrightGreen: t => t, + bgBrightYellow: t => t, + bgBrightBlue: t => t, + bgBrightMagenta: t => t, + bgBrightCyan: t => t, + bgBrightWhite: t => t +}; + + +const applyStyle = (open: number, close: number, text: string) => `\u001b[${open}m${text}\u001b[${close}m`; diff --git a/packages/playwright-core/src/utils/stackTrace.ts b/packages/playwright-core/src/utils/isomorphic/stackTrace.ts similarity index 84% rename from packages/playwright-core/src/utils/stackTrace.ts rename to packages/playwright-core/src/utils/isomorphic/stackTrace.ts index d3331698d1..7ce3f719a4 100644 --- a/packages/playwright-core/src/utils/stackTrace.ts +++ b/packages/playwright-core/src/utils/isomorphic/stackTrace.ts @@ -14,16 +14,14 @@ * limitations under the License. */ -import * as path from 'path'; - -import { colors } from '../utilsBundle'; -import { findRepeatedSubsequences } from './isomorphic/sequence'; +import { colors } from './colors'; +import { findRepeatedSubsequences } from './sequence'; import { parseStackFrame } from './stackUtils'; import type { StackFrame } from '@protocol/channels'; -export function parseStackTraceLine(line: string): StackFrame | null { - const frame = parseStackFrame(line); +export function parseStackTraceLine(line: string, pathSeparator: string): StackFrame | null { + const frame = parseStackFrame(line, pathSeparator); if (!frame) return null; if (!process.env.PWDEBUGIMPL && (frame.file?.startsWith('internal') || frame.file?.startsWith('node:'))) @@ -47,12 +45,15 @@ export function rewriteErrorMessage(e: E, newMessage: string): return e; } -const CORE_DIR = path.resolve(__dirname, '..', '..'); +let coreDir: string | undefined; -const internalStackPrefixes = [ - CORE_DIR, -]; -export const addInternalStackPrefix = (prefix: string) => internalStackPrefixes.push(prefix); +const playwrightStackPrefixes: string[] = []; +export const addInternalStackPrefix = (prefix: string) => playwrightStackPrefixes.push(prefix); + +export const setLibraryStackPrefix = (prefix: string) => { + coreDir = prefix; + playwrightStackPrefixes.push(prefix); +}; export type RawStack = string[]; @@ -65,7 +66,7 @@ export function captureRawStack(): RawStack { return stack.split('\n'); } -export function captureLibraryStackTrace(): { frames: StackFrame[], apiName: string } { +export function captureLibraryStackTrace(pathSeparator: string): { frames: StackFrame[], apiName: string } { const stack = captureRawStack(); type ParsedFrame = { @@ -74,10 +75,10 @@ export function captureLibraryStackTrace(): { frames: StackFrame[], apiName: str isPlaywrightLibrary: boolean; }; let parsedFrames = stack.map(line => { - const frame = parseStackTraceLine(line); + const frame = parseStackTraceLine(line, pathSeparator); if (!frame || !frame.file) return null; - const isPlaywrightLibrary = frame.file.startsWith(CORE_DIR); + const isPlaywrightLibrary = !!coreDir && frame.file.startsWith(coreDir); const parsed: ParsedFrame = { frame, frameText: line, @@ -111,7 +112,7 @@ export function captureLibraryStackTrace(): { frames: StackFrame[], apiName: str parsedFrames = parsedFrames.filter(f => { if (process.env.PWDEBUGIMPL) return true; - if (internalStackPrefixes.some(prefix => f.frame.file.startsWith(prefix))) + if (playwrightStackPrefixes.some(prefix => f.frame.file.startsWith(prefix))) return false; return true; }); @@ -133,11 +134,6 @@ export function stringifyStackFrames(frames: StackFrame[]): string[] { return stackLines; } -export function captureLibraryStackText() { - const parsed = captureLibraryStackTrace(); - return stringifyStackFrames(parsed.frames).join('\n'); -} - export function splitErrorMessage(message: string): { name: string, message: string } { const separationIdx = message.indexOf(':'); return { diff --git a/packages/playwright-core/src/utils/stackUtils.ts b/packages/playwright-core/src/utils/isomorphic/stackUtils.ts similarity index 88% rename from packages/playwright-core/src/utils/stackUtils.ts rename to packages/playwright-core/src/utils/isomorphic/stackUtils.ts index 024b6fe8d0..20be8081af 100644 --- a/packages/playwright-core/src/utils/stackUtils.ts +++ b/packages/playwright-core/src/utils/isomorphic/stackUtils.ts @@ -19,8 +19,6 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import * as url from 'url'; - type StackData = { line?: number; column?: number; @@ -35,7 +33,7 @@ type StackData = { evalFile?: string | undefined; }; -export function parseStackFrame(line: string): StackData | null { +export function parseStackFrame(line: string, pathSeparator: string): StackData | null { const match = line && line.match(re); if (!match) return null; @@ -92,7 +90,7 @@ export function parseStackFrame(line: string): StackData | null { } } - setFile(res, file); + setFile(res, file, pathSeparator); if (ctor) res.isConstructor = true; @@ -113,10 +111,10 @@ export function parseStackFrame(line: string): StackData | null { return res; } -function setFile(result: StackData, filename: string) { +function setFile(result: StackData, filename: string, pathSeparator: string) { if (filename) { if (filename.startsWith('file://')) - filename = url.fileURLToPath(filename); + filename = fileURLToPath(filename, pathSeparator); result.file = filename; } } @@ -147,3 +145,14 @@ const re = new RegExp('^' + ); const methodRe = /^(.*?) \[as (.*?)\]$/; + +function fileURLToPath(fileUrl: string, pathSeparator: string): string { + if (!fileUrl.startsWith('file://')) + return fileUrl; + + let path = decodeURIComponent(fileUrl.slice(7)); + if (path.startsWith('/') && /^[a-zA-Z]:/.test(path.slice(1))) + path = path.slice(1); + + return path.replace(/\//g, pathSeparator); +} diff --git a/packages/playwright-core/src/utils/platform.ts b/packages/playwright-core/src/utils/platform.ts index 60f2cdbd3a..5abf38e8c0 100644 --- a/packages/playwright-core/src/utils/platform.ts +++ b/packages/playwright-core/src/utils/platform.ts @@ -25,6 +25,7 @@ export type Platform = { fs: () => typeof fs; inspectCustom: symbol | undefined; path: () => typeof path; + pathSeparator: string; ws?: (url: string) => WebSocket; }; @@ -42,6 +43,8 @@ export const nodePlatform: Platform = { inspectCustom: util.inspect.custom, path: () => path, + + pathSeparator: path.sep }; export const webPlatform: Platform = { @@ -65,5 +68,7 @@ export const webPlatform: Platform = { throw new Error('Path module is not available'); }, + pathSeparator: '/', + ws: (url: string) => new WebSocket(url), }; diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index 41cccd1f57..a72f18c30f 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -export const colors: typeof import('../bundles/utils/node_modules/colors/safe') = require('./utilsBundleImpl').colors; export const debug: typeof import('../bundles/utils/node_modules/@types/debug') = require('./utilsBundleImpl').debug; export const diff: typeof import('../bundles/utils/node_modules/@types/diff') = require('./utilsBundleImpl').diff; export const dotenv: typeof import('../bundles/utils/node_modules/dotenv') = require('./utilsBundleImpl').dotenv; diff --git a/packages/playwright/src/matchers/matcherHint.ts b/packages/playwright/src/matchers/matcherHint.ts index 1dfa1ceb4a..316ecad685 100644 --- a/packages/playwright/src/matchers/matcherHint.ts +++ b/packages/playwright/src/matchers/matcherHint.ts @@ -15,7 +15,7 @@ */ import { stringifyStackFrames } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import type { ExpectMatcherState } from '../../types/test'; import type { StackFrame } from '@protocol/channels'; diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index 2890feaac6..d37e3285f4 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -15,7 +15,7 @@ */ import { isRegExp, isString, isTextualMimeType, pollAgainstDeadline, serializeExpectedTextValues } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { callLogText, expectTypes } from '../util'; import { toBeTruthy } from './toBeTruthy'; diff --git a/packages/playwright/src/matchers/toHaveURL.ts b/packages/playwright/src/matchers/toHaveURL.ts index c56441fee5..efc0ebd5f2 100644 --- a/packages/playwright/src/matchers/toHaveURL.ts +++ b/packages/playwright/src/matchers/toHaveURL.ts @@ -15,7 +15,7 @@ */ import { constructURLBasedOnBaseURL, urlMatches } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { printReceivedStringContainExpectedResult, printReceivedStringContainExpectedSubstring } from './expect'; import { matcherHint } from './matcherHint'; diff --git a/packages/playwright/src/matchers/toMatchSnapshot.ts b/packages/playwright/src/matchers/toMatchSnapshot.ts index 220c948887..dd54e61aeb 100644 --- a/packages/playwright/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchSnapshot.ts @@ -18,7 +18,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { compareBuffersOrStrings, getComparator, isString, sanitizeForFilePath } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { mime } from 'playwright-core/lib/utilsBundle'; import { diff --git a/packages/playwright/src/matchers/toMatchText.ts b/packages/playwright/src/matchers/toMatchText.ts index 961937eb5b..142013f1b5 100644 --- a/packages/playwright/src/matchers/toMatchText.ts +++ b/packages/playwright/src/matchers/toMatchText.ts @@ -15,7 +15,7 @@ */ -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { callLogText, expectTypes } from '../util'; import { diff --git a/packages/playwright/src/plugins/webServerPlugin.ts b/packages/playwright/src/plugins/webServerPlugin.ts index 62583c303e..4bb1bef0db 100644 --- a/packages/playwright/src/plugins/webServerPlugin.ts +++ b/packages/playwright/src/plugins/webServerPlugin.ts @@ -17,7 +17,8 @@ import * as net from 'net'; import * as path from 'path'; import { launchProcess, isURLAvailable, monotonicTime, raceAgainstDeadline } from 'playwright-core/lib/utils'; -import { colors, debug } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; +import { debug } from 'playwright-core/lib/utilsBundle'; import type { TestRunnerPlugin } from '.'; import type { FullConfig } from '../../types/testReporter'; diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 156f9755db..8ba5b23af1 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -18,7 +18,8 @@ import * as path from 'path'; import { getPackageManagerExecCommand } from 'playwright-core/lib/utils'; import { parseStackTraceLine } from 'playwright-core/lib/utils'; -import { colors as realColors, ms as milliseconds } from 'playwright-core/lib/utilsBundle'; +import { ms as milliseconds } from 'playwright-core/lib/utilsBundle'; +import { colors as realColors, noColors } from 'playwright-core/lib/utils'; import { resolveReporterOutputPath } from '../util'; import { getEastAsianWidth } from '../utilsBundle'; @@ -53,48 +54,6 @@ export type Screen = { ttyWidth: number; }; -export const noColors: Colors = { - bold: (t: string) => t, - cyan: (t: string) => t, - dim: (t: string) => t, - gray: (t: string) => t, - green: (t: string) => t, - red: (t: string) => t, - yellow: (t: string) => t, - black: (t: string) => t, - blue: (t: string) => t, - magenta: (t: string) => t, - white: (t: string) => t, - grey: (t: string) => t, - bgBlack: (t: string) => t, - bgRed: (t: string) => t, - bgGreen: (t: string) => t, - bgYellow: (t: string) => t, - bgBlue: (t: string) => t, - bgMagenta: (t: string) => t, - bgCyan: (t: string) => t, - bgWhite: (t: string) => t, - strip: (t: string) => t, - stripColors: (t: string) => t, - reset: (t: string) => t, - italic: (t: string) => t, - underline: (t: string) => t, - inverse: (t: string) => t, - hidden: (t: string) => t, - strikethrough: (t: string) => t, - rainbow: (t: string) => t, - zebra: (t: string) => t, - america: (t: string) => t, - trap: (t: string) => t, - random: (t: string) => t, - zalgo: (t: string) => t, - - enabled: false, - enable: () => {}, - disable: () => {}, - setTheme: () => {}, -}; - // Output goes to terminal. export const terminalScreen: Screen = (() => { let isTTY = !!process.stdout.isTTY; @@ -563,7 +522,7 @@ export function prepareErrorStack(stack: string): { const stackLines = lines.slice(firstStackLine); let location: Location | undefined; for (const line of stackLines) { - const frame = parseStackTraceLine(line); + const frame = parseStackTraceLine(line, path.sep); if (!frame || !frame.file) continue; if (belongsToNodeModules(frame.file)) diff --git a/packages/playwright/src/reporters/github.ts b/packages/playwright/src/reporters/github.ts index e3677dd3ff..7c65c00b3c 100644 --- a/packages/playwright/src/reporters/github.ts +++ b/packages/playwright/src/reporters/github.ts @@ -16,9 +16,10 @@ import * as path from 'path'; +import { noColors } from 'playwright-core/lib/utils'; import { ms as milliseconds } from 'playwright-core/lib/utilsBundle'; -import { TerminalReporter, formatResultFailure, formatRetry, noColors, stripAnsiEscapes } from './base'; +import { TerminalReporter, formatResultFailure, formatRetry, stripAnsiEscapes } from './base'; import type { FullResult, TestCase, TestError } from '../../types/testReporter'; diff --git a/packages/playwright/src/reporters/html.ts b/packages/playwright/src/reporters/html.ts index 3390a71746..a86a758d48 100644 --- a/packages/playwright/src/reporters/html.ts +++ b/packages/playwright/src/reporters/html.ts @@ -19,7 +19,8 @@ import * as path from 'path'; import { Transform } from 'stream'; import { HttpServer, MultiMap, assert, calculateSha1, getPackageManagerExecCommand, copyFileAndMakeWritable, gracefullyProcessExitDoNotHang, removeFolders, sanitizeForFilePath, toPosixPath } from 'playwright-core/lib/utils'; -import { colors, open } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; +import { open } from 'playwright-core/lib/utilsBundle'; import { mime } from 'playwright-core/lib/utilsBundle'; import { yazl } from 'playwright-core/lib/zipBundle'; diff --git a/packages/playwright/src/runner/dispatcher.ts b/packages/playwright/src/runner/dispatcher.ts index 084deba11d..cf0c7144c0 100644 --- a/packages/playwright/src/runner/dispatcher.ts +++ b/packages/playwright/src/runner/dispatcher.ts @@ -15,7 +15,7 @@ */ import { ManualPromise, eventsHelper } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { addSuggestedRebaseline } from './rebase'; import { WorkerHost } from './workerHost'; diff --git a/packages/playwright/src/runner/rebase.ts b/packages/playwright/src/runner/rebase.ts index c2d9f96d18..ef7d49f013 100644 --- a/packages/playwright/src/runner/rebase.ts +++ b/packages/playwright/src/runner/rebase.ts @@ -19,7 +19,8 @@ import * as path from 'path'; import { MultiMap } from 'playwright-core/lib/utils'; -import { colors, diff } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; +import { diff } from 'playwright-core/lib/utilsBundle'; import { filterProjects } from './projectUtils'; import { babelParse, traverse, types } from '../transform/babelBundle'; diff --git a/packages/playwright/src/runner/taskRunner.ts b/packages/playwright/src/runner/taskRunner.ts index 12185aa951..ea0561faaa 100644 --- a/packages/playwright/src/runner/taskRunner.ts +++ b/packages/playwright/src/runner/taskRunner.ts @@ -15,7 +15,8 @@ */ import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils'; -import { colors, debug } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; +import { debug } from 'playwright-core/lib/utilsBundle'; import { SigIntWatcher } from './sigIntWatcher'; diff --git a/packages/playwright/src/runner/watchMode.ts b/packages/playwright/src/runner/watchMode.ts index c9768c47ba..ad819853fc 100644 --- a/packages/playwright/src/runner/watchMode.ts +++ b/packages/playwright/src/runner/watchMode.ts @@ -20,7 +20,7 @@ import { EventEmitter } from 'stream'; import { PlaywrightServer } from 'playwright-core/lib/remote/playwrightServer'; import { ManualPromise, createGuid, eventsHelper, getPackageManagerExecCommand } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { separator, terminalScreen } from '../reporters/base'; import { enquirer } from '../utilsBundle'; diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 803aa73f6b..a890535fee 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -55,7 +55,7 @@ export function filterStackFile(file: string) { export function filteredStackTrace(rawStack: RawStack): StackFrame[] { const frames: StackFrame[] = []; for (const line of rawStack) { - const frame = parseStackTraceLine(line); + const frame = parseStackTraceLine(line, path.sep); if (!frame || !frame.file) continue; if (!filterStackFile(frame.file)) diff --git a/packages/playwright/src/worker/timeoutManager.ts b/packages/playwright/src/worker/timeoutManager.ts index 7018dafcc9..65e97c9f36 100644 --- a/packages/playwright/src/worker/timeoutManager.ts +++ b/packages/playwright/src/worker/timeoutManager.ts @@ -15,7 +15,7 @@ */ import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import type { Location } from '../../types/testReporter'; diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index 30b59c36e7..e09579d0e0 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -15,7 +15,7 @@ */ import { ManualPromise, gracefullyCloseAll, removeFolders } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors } from 'playwright-core/lib/utils'; import { deserializeConfig } from '../common/configLoader'; import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals'; From bab197b4938552cd1b5956ce61ad4f3a92b700dc Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 12 Feb 2025 18:04:42 -0800 Subject: [PATCH 02/13] test: adjust bidi browser name in browsertype-connect.spec (#34758) --- tests/library/browsertype-connect.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index e4118e489f..c0475ab57e 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -258,7 +258,9 @@ for (const kind of ['launchServer', 'run-server'] as const) { }).catch(() => {}) ]); expect(request.headers['user-agent']).toBe(getUserAgent()); - expect(request.headers['x-playwright-browser']).toBe(browserName); + // _bidiFirefox and _bidiChromium are initialized with 'bidi' as browser name. + const bidiAwareBrowserName = browserName.startsWith('_bidi') ? 'bidi' : browserName; + expect(request.headers['x-playwright-browser']).toBe(bidiAwareBrowserName); expect(request.headers['foo']).toBe('bar'); }); From 6951e6ad9d08a34164a5c7a4fd0e8a2415f7b23e Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 12 Feb 2025 18:14:39 -0800 Subject: [PATCH 03/13] chore(bidi): move private handle conversion to execution context (#34765) --- .../src/server/bidi/bidiExecutionContext.ts | 41 ++++++++++++++++++- .../src/server/bidi/bidiPage.ts | 41 +++++-------------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts index ec0cb681a0..aea4672196 100644 --- a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts +++ b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts @@ -16,6 +16,7 @@ import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers'; import * as js from '../javascript'; +import * as dom from '../dom'; import { BidiDeserializer } from './third_party/bidiDeserializer'; import * as bidi from './third_party/bidiProtocol'; import { BidiSerializer } from './third_party/bidiSerializer'; @@ -137,7 +138,45 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate { }); } - async rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise { + + async nodeIdForElementHandle(handle: dom.ElementHandle): Promise { + const shared = await this._remoteValueForReference({ handle: handle._objectId }); + // TODO: store sharedId in the handle. + if (!('sharedId' in shared)) + throw new Error('Element is not a node'); + return { + sharedId: shared.sharedId!, + }; + } + + async remoteObjectForNodeId(nodeId: bidi.Script.SharedReference): Promise { + const result = await this._remoteValueForReference(nodeId); + if ('handle' in result) + return { objectId: result.handle!, ...result }; + throw new Error('Can\'t get remote object for nodeId'); + } + + async contentFrameIdForFrame(handle: dom.ElementHandle) { + const contentWindow = await this._rawCallFunction('e => e.contentWindow', { handle: handle._objectId }); + if (contentWindow?.type === 'window') + return contentWindow.value.context; + return null; + } + + async frameIdForWindowHandle(handle: js.JSHandle): Promise { + if (!handle._objectId) + throw new Error('JSHandle is not a DOM node handle'); + const contentWindow = await this._remoteValueForReference({ handle: handle._objectId }); + if (contentWindow.type === 'window') + return contentWindow.value.context; + return null; + } + + private async _remoteValueForReference(reference: bidi.Script.RemoteReference) { + return await this._rawCallFunction('e => e', reference); + } + + private async _rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise { const response = await this._session.send('script.callFunction', { functionDeclaration, target: this._target, diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 0ee5822f93..badd68d1a1 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -413,13 +413,10 @@ export class BidiPage implements PageDelegate { async getContentFrame(handle: dom.ElementHandle): Promise { const executionContext = toBidiExecutionContext(handle._context); - const contentWindow = await executionContext.rawCallFunction('e => e.contentWindow', { handle: handle._objectId }); - if (contentWindow.type === 'window') { - const frameId = contentWindow.value.context; - const result = this._page._frameManager.frame(frameId); - return result; - } - return null; + const frameId = await executionContext.contentFrameIdForFrame(handle); + if (!frameId) + return null; + return this._page._frameManager.frame(frameId); } async getOwnerFrame(handle: dom.ElementHandle): Promise { @@ -430,15 +427,8 @@ export class BidiPage implements PageDelegate { }); if (!windowHandle) return null; - if (!windowHandle._objectId) - return null; - const executionContext = toBidiExecutionContext(windowHandle._context as dom.FrameExecutionContext); - const contentWindow = await executionContext.rawCallFunction('e => e', { handle: windowHandle._objectId }); - if (contentWindow.type === 'window') { - const frameId = contentWindow.value.context; - return frameId; - } - return null; + const executionContext = toBidiExecutionContext(handle._context); + return executionContext.frameIdForWindowHandle(windowHandle); } isElementHandle(remoteObject: bidi.Script.RemoteValue): boolean { @@ -535,29 +525,20 @@ export class BidiPage implements PageDelegate { async setInputFilePaths(handle: dom.ElementHandle, paths: string[]): Promise { const fromContext = toBidiExecutionContext(handle._context); - const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId }); - // TODO: store sharedId in the handle. - if (!('sharedId' in shared)) - throw new Error('Element is not a node'); - const sharedId = shared.sharedId!; await this._session.send('input.setFiles', { context: this._session.sessionId, - element: { sharedId }, + element: await fromContext.nodeIdForElementHandle(handle), files: paths, }); } async adoptElementHandle(handle: dom.ElementHandle, to: dom.FrameExecutionContext): Promise> { const fromContext = toBidiExecutionContext(handle._context); - const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId }); - // TODO: store sharedId in the handle. - if (!('sharedId' in shared)) - throw new Error('Element is not a node'); - const sharedId = shared.sharedId!; + const nodeId = await fromContext.nodeIdForElementHandle(handle); const executionContext = toBidiExecutionContext(to); - const result = await executionContext.rawCallFunction('x => x', { sharedId }); - if ('handle' in result) - return to.createHandle({ objectId: result.handle!, ...result }) as dom.ElementHandle; + const objectId = await executionContext.remoteObjectForNodeId(nodeId); + if (objectId) + return to.createHandle(objectId) as dom.ElementHandle; throw new Error('Failed to adopt element handle.'); } From 3d760b657b838ba23ab76d33fa16b45a48b4b7de Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 12 Feb 2025 19:27:24 -0800 Subject: [PATCH 04/13] chore: move debug, env and user agent from utils/ (#34766) --- packages/playwright-core/src/DEPS.list | 3 + .../playwright-core/src/client/android.ts | 4 +- .../playwright-core/src/client/artifact.ts | 2 +- .../playwright-core/src/client/browser.ts | 2 +- .../src/client/browserContext.ts | 6 +- .../playwright-core/src/client/browserType.ts | 2 +- .../src/client/channelOwner.ts | 15 +++-- .../src/client/clientHelper.ts | 2 +- .../playwright-core/src/client/connection.ts | 15 +++-- .../src/client/consoleMessage.ts | 2 +- .../playwright-core/src/client/electron.ts | 2 +- .../src/client/elementHandle.ts | 6 +- .../src/client/eventEmitter.ts | 2 +- packages/playwright-core/src/client/fetch.ts | 6 +- packages/playwright-core/src/client/frame.ts | 2 +- .../playwright-core/src/client/harRouter.ts | 6 +- .../playwright-core/src/client/localUtils.ts | 6 +- .../playwright-core/src/client/network.ts | 2 +- packages/playwright-core/src/client/page.ts | 6 +- .../playwright-core/src/client/selectors.ts | 10 +++- packages/playwright-core/src/common/DEPS.list | 1 + .../src/{utils => common}/fileUtils.ts | 0 .../src/{utils => common}/harBackend.ts | 4 +- .../src/{utils => common}/localUtils.ts | 6 +- .../src/{utils => common}/platform.ts | 56 ++++++++++++------- .../playwright-core/src/inProcessFactory.ts | 10 +++- packages/playwright-core/src/inprocess.ts | 2 +- packages/playwright-core/src/outofprocess.ts | 2 +- .../src/remote/playwrightConnection.ts | 2 +- .../src/remote/playwrightServer.ts | 4 +- .../src/server/android/DEPS.list | 1 + .../src/server/android/android.ts | 8 +-- .../src/server/android/backendAdb.ts | 2 +- .../src/server/bidi/bidiConnection.ts | 4 +- .../src/server/bidi/bidiOverCdp.ts | 2 +- .../playwright-core/src/server/browser.ts | 2 +- .../src/server/browserContext.ts | 4 +- .../playwright-core/src/server/browserType.ts | 4 +- .../src/server/chromium/chromium.ts | 6 +- .../src/server/chromium/crBrowser.ts | 2 +- .../src/server/chromium/crConnection.ts | 4 +- .../src/server/chromium/crPage.ts | 2 +- .../dispatchers/localUtilsDispatcher.ts | 8 +-- .../src/server/electron/DEPS.list | 1 + .../src/server/electron/electron.ts | 4 +- packages/playwright-core/src/server/fetch.ts | 4 +- .../src/server/fileUploadUtils.ts | 4 +- .../src/server/firefox/ffConnection.ts | 4 +- .../src/server/firefox/ffPage.ts | 2 +- packages/playwright-core/src/server/frames.ts | 2 +- packages/playwright-core/src/server/helper.ts | 2 +- packages/playwright-core/src/server/page.ts | 4 +- .../src/server/pipeTransport.ts | 2 +- .../playwright-core/src/server/progress.ts | 2 +- .../src/server/recorder/recorderCollection.ts | 2 +- .../src/server/registry/browserFetcher.ts | 4 +- .../src/server/registry/dependencies.ts | 4 +- .../src/server/registry/index.ts | 8 +-- .../socksClientCertificatesInterceptor.ts | 2 +- .../src/server/trace/recorder/snapshotter.ts | 2 +- .../src/server/trace/recorder/tracing.ts | 2 +- .../src/server/utils/DEPS.list | 1 + .../src/server/utils/crypto.ts | 2 +- .../src/{ => server}/utils/debugLogger.ts | 2 +- .../src/{ => server}/utils/env.ts | 0 .../src/server/utils/happyEyeballs.ts | 2 +- .../src/{ => server}/utils/hostPlatform.ts | 0 .../src/server/utils/httpServer.ts | 2 +- .../src/{ => server}/utils/linuxUtils.ts | 20 ------- .../src/server/utils/nodePlatform.ts | 49 ++++++++++++++++ .../src/server/utils/socksProxy.ts | 4 +- .../src/{ => server}/utils/userAgent.ts | 2 +- .../src/server/utils/wsServer.ts | 2 +- .../src/server/webkit/wkConnection.ts | 4 +- .../src/server/webkit/wkPage.ts | 4 +- packages/playwright-core/src/utils.ts | 11 ++-- .../src/utils/{ => isomorphic}/debug.ts | 15 +++-- .../isomorphic}/timeoutSettings.ts | 2 +- tests/library/browsertype-connect.spec.ts | 2 +- tests/library/capabilities.spec.ts | 2 +- .../library/chromium/connect-over-cdp.spec.ts | 2 +- .../events/check-listener-leaks.spec.ts | 2 +- tests/library/global-fetch.spec.ts | 2 +- tests/library/inspector/inspectorTest.ts | 2 +- tests/library/modernizr.spec.ts | 2 +- tests/playwright-test/reporter-blob.spec.ts | 2 +- 86 files changed, 248 insertions(+), 182 deletions(-) rename packages/playwright-core/src/{utils => common}/fileUtils.ts (100%) rename packages/playwright-core/src/{utils => common}/harBackend.ts (98%) rename packages/playwright-core/src/{utils => common}/localUtils.ts (98%) rename packages/playwright-core/src/{utils => common}/platform.ts (68%) rename packages/playwright-core/src/{ => server}/utils/debugLogger.ts (98%) rename packages/playwright-core/src/{ => server}/utils/env.ts (100%) rename packages/playwright-core/src/{ => server}/utils/hostPlatform.ts (100%) rename packages/playwright-core/src/{ => server}/utils/linuxUtils.ts (73%) create mode 100644 packages/playwright-core/src/server/utils/nodePlatform.ts rename packages/playwright-core/src/{ => server}/utils/userAgent.ts (98%) rename packages/playwright-core/src/utils/{ => isomorphic}/debug.ts (83%) rename packages/playwright-core/src/{common => utils/isomorphic}/timeoutSettings.ts (98%) diff --git a/packages/playwright-core/src/DEPS.list b/packages/playwright-core/src/DEPS.list index ec14e89070..2ffa077b4e 100644 --- a/packages/playwright-core/src/DEPS.list +++ b/packages/playwright-core/src/DEPS.list @@ -8,10 +8,13 @@ ** [inprocess.ts] +common/ utils/ +server/utils [outofprocess.ts] client/ +common/ protocol/ utils/ utils/isomorphic diff --git a/packages/playwright-core/src/client/android.ts b/packages/playwright-core/src/client/android.ts index f6e0419c2c..f0ca11848f 100644 --- a/packages/playwright-core/src/client/android.ts +++ b/packages/playwright-core/src/client/android.ts @@ -21,7 +21,7 @@ import { ChannelOwner } from './channelOwner'; import { TargetClosedError, isTargetClosedError } from './errors'; import { Events } from './events'; import { Waiter } from './waiter'; -import { TimeoutSettings } from '../common/timeoutSettings'; +import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; import { monotonicTime } from '../utils/isomorphic/time'; import { raceAgainstDeadline } from '../utils/isomorphic/timeoutRunner'; @@ -30,7 +30,7 @@ import type { Page } from './page'; import type * as types from './types'; import type * as api from '../../types/types'; import type { AndroidServerLauncherImpl } from '../androidServerImpl'; -import type { Platform } from '../utils/platform'; +import type { Platform } from '../common/platform'; import type * as channels from '@protocol/channels'; type Direction = 'down' | 'up' | 'left' | 'right'; diff --git a/packages/playwright-core/src/client/artifact.ts b/packages/playwright-core/src/client/artifact.ts index fc1e9bca12..815c7a358b 100644 --- a/packages/playwright-core/src/client/artifact.ts +++ b/packages/playwright-core/src/client/artifact.ts @@ -16,7 +16,7 @@ import { ChannelOwner } from './channelOwner'; import { Stream } from './stream'; -import { mkdirIfNeeded } from '../utils/fileUtils'; +import { mkdirIfNeeded } from '../common/fileUtils'; import type * as channels from '@protocol/channels'; import type { Readable } from 'stream'; diff --git a/packages/playwright-core/src/client/browser.ts b/packages/playwright-core/src/client/browser.ts index 9d2ca1fab0..88140621fe 100644 --- a/packages/playwright-core/src/client/browser.ts +++ b/packages/playwright-core/src/client/browser.ts @@ -20,7 +20,7 @@ import { CDPSession } from './cdpSession'; import { ChannelOwner } from './channelOwner'; import { isTargetClosedError } from './errors'; import { Events } from './events'; -import { mkdirIfNeeded } from '../utils/fileUtils'; +import { mkdirIfNeeded } from '../common/fileUtils'; import type { BrowserType } from './browserType'; import type { Page } from './page'; diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index 32cac6ba7f..02aa857366 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -34,8 +34,8 @@ import { Tracing } from './tracing'; import { Waiter } from './waiter'; import { WebError } from './webError'; import { Worker } from './worker'; -import { TimeoutSettings } from '../common/timeoutSettings'; -import { mkdirIfNeeded } from '../utils/fileUtils'; +import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; +import { mkdirIfNeeded } from '../common/fileUtils'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { urlMatchesEqual } from '../utils/isomorphic/urlMatch'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; @@ -46,7 +46,7 @@ import type { BrowserContextOptions, Headers, LaunchOptions, StorageState, WaitF import type * as structs from '../../types/structs'; import type * as api from '../../types/types'; import type { URLMatch } from '../utils/isomorphic/urlMatch'; -import type { Platform } from '../utils/platform'; +import type { Platform } from '../common/platform'; import type * as channels from '@protocol/channels'; export class BrowserContext extends ChannelOwner implements api.BrowserContext { diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index 79d2fbd521..06bae0419f 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -21,7 +21,7 @@ import { BrowserContext, prepareBrowserContextParams } from './browserContext'; import { ChannelOwner } from './channelOwner'; import { envObjectToArray } from './clientHelper'; import { Events } from './events'; -import { assert } from '../utils/debug'; +import { assert } from '../utils/isomorphic/debug'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { monotonicTime } from '../utils/isomorphic/time'; import { raceAgainstDeadline } from '../utils/isomorphic/timeoutRunner'; diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 5c5afcdc2d..40bf226c65 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -16,8 +16,7 @@ import { EventEmitter } from './eventEmitter'; import { ValidationError, maybeFindValidator } from '../protocol/validator'; -import { isUnderTest } from '../utils/debug'; -import { debugLogger } from '../utils/debugLogger'; +import { isUnderTest } from '../utils/isomorphic/debug'; import { captureLibraryStackTrace, stringifyStackFrames } from '../utils/isomorphic/stackTrace'; import { zones } from '../utils/zones'; @@ -25,7 +24,7 @@ import type { ClientInstrumentation } from './clientInstrumentation'; import type { Connection } from './connection'; import type { Logger } from './types'; import type { ValidatorContext } from '../protocol/validator'; -import type { Platform } from '../utils/platform'; +import type { Platform } from '../common/platform'; import type * as channels from '@protocol/channels'; type Listener = (...args: any[]) => void; @@ -158,7 +157,7 @@ export abstract class ChannelOwner ${apiZone.apiName} started`); + logApiCall(this._platform, this._logger, `=> ${apiZone.apiName} started`); return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone.apiName, apiZone.frames, apiZone.stepId); } // Since this api call is either internal, or has already been reported/traced once, @@ -189,7 +188,7 @@ export abstract class ChannelOwner await func(apiZone)); if (!isInternal) { - logApiCall(logger, `<= ${apiZone.apiName} succeeded`); + logApiCall(this._platform, logger, `<= ${apiZone.apiName} succeeded`); this._instrumentation.onApiCallEnd(apiZone); } return result; @@ -204,7 +203,7 @@ export abstract class ChannelOwner { @@ -139,9 +138,9 @@ export class Connection extends EventEmitter { const type = object._type; const id = ++this._lastId; const message = { id, guid, method, params }; - if (debugLogger.isEnabled('channel')) { + if (this.platform.isLogEnabled('channel')) { // Do not include metadata in debug logs to avoid noise. - debugLogger.log('channel', 'SEND> ' + JSON.stringify(message)); + this.platform.log('channel', 'SEND> ' + JSON.stringify(message)); } const location = frames[0] ? { file: frames[0].file, line: frames[0].line, column: frames[0].column } : undefined; const metadata: channels.Metadata = { apiName, location, internal: !apiName, stepId }; @@ -159,8 +158,8 @@ export class Connection extends EventEmitter { const { id, guid, method, params, result, error, log } = message as any; if (id) { - if (debugLogger.isEnabled('channel')) - debugLogger.log('channel', '(); private _registrations: channels.SelectorsRegisterParams[] = []; async register(name: string, script: string | (() => SelectorEngine) | { path?: string, content?: string }, options: { contentScript?: boolean } = {}): Promise { - const source = await evaluationScript(nodePlatform, script, undefined, false); + const source = await evaluationScript(platform, script, undefined, false); const params = { ...options, name, source }; for (const channel of this._channels) await channel._channel.register(params); diff --git a/packages/playwright-core/src/common/DEPS.list b/packages/playwright-core/src/common/DEPS.list index 43bff9dba4..a25dd41c36 100644 --- a/packages/playwright-core/src/common/DEPS.list +++ b/packages/playwright-core/src/common/DEPS.list @@ -1,4 +1,5 @@ [*] ../utils/ +../utils/isomorphic/ ../utilsBundle.ts ../zipBundle.ts diff --git a/packages/playwright-core/src/utils/fileUtils.ts b/packages/playwright-core/src/common/fileUtils.ts similarity index 100% rename from packages/playwright-core/src/utils/fileUtils.ts rename to packages/playwright-core/src/common/fileUtils.ts diff --git a/packages/playwright-core/src/utils/harBackend.ts b/packages/playwright-core/src/common/harBackend.ts similarity index 98% rename from packages/playwright-core/src/utils/harBackend.ts rename to packages/playwright-core/src/common/harBackend.ts index 304fe4b150..f59b7de5f1 100644 --- a/packages/playwright-core/src/utils/harBackend.ts +++ b/packages/playwright-core/src/common/harBackend.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { ZipFile } from './zipFile'; +import { ZipFile } from '../utils/zipFile'; -import type { HeadersArray } from '../common/types'; +import type { HeadersArray } from './types'; import type * as har from '@trace/har'; import type { Platform } from './platform'; diff --git a/packages/playwright-core/src/utils/localUtils.ts b/packages/playwright-core/src/common/localUtils.ts similarity index 98% rename from packages/playwright-core/src/utils/localUtils.ts rename to packages/playwright-core/src/common/localUtils.ts index 49a3c43175..5020d82b75 100644 --- a/packages/playwright-core/src/utils/localUtils.ts +++ b/packages/playwright-core/src/common/localUtils.ts @@ -20,11 +20,11 @@ import * as path from 'path'; import { removeFolders } from './fileUtils'; import { HarBackend } from './harBackend'; -import { ManualPromise } from './isomorphic/manualPromise'; -import { ZipFile } from './zipFile'; +import { ManualPromise } from '../utils/isomorphic/manualPromise'; +import { ZipFile } from '../utils/zipFile'; import { yauzl, yazl } from '../zipBundle'; import { serializeClientSideCallMetadata } from '../utils/isomorphic/traceUtils'; -import { assert } from '../utils/debug'; +import { assert } from '../utils/isomorphic/debug'; import type { Platform } from './platform'; import type * as channels from '@protocol/channels'; diff --git a/packages/playwright-core/src/utils/platform.ts b/packages/playwright-core/src/common/platform.ts similarity index 68% rename from packages/playwright-core/src/utils/platform.ts rename to packages/playwright-core/src/common/platform.ts index 5abf38e8c0..390dbf80ff 100644 --- a/packages/playwright-core/src/utils/platform.ts +++ b/packages/playwright-core/src/common/platform.ts @@ -17,36 +17,19 @@ import * as crypto from 'crypto'; import * as fs from 'fs'; import * as path from 'path'; -import * as util from 'util'; export type Platform = { calculateSha1(text: string): Promise; createGuid: () => string; fs: () => typeof fs; inspectCustom: symbol | undefined; + isLogEnabled(name: 'api' | 'channel'): boolean; + log(name: 'api' | 'channel', message: string | Error | object): void; path: () => typeof path; pathSeparator: string; ws?: (url: string) => WebSocket; }; -export const nodePlatform: Platform = { - calculateSha1: (text: string) => { - const sha1 = crypto.createHash('sha1'); - sha1.update(text); - return Promise.resolve(sha1.digest('hex')); - }, - - createGuid: () => crypto.randomBytes(16).toString('hex'), - - fs: () => fs, - - inspectCustom: util.inspect.custom, - - path: () => path, - - pathSeparator: path.sep -}; - export const webPlatform: Platform = { calculateSha1: async (text: string) => { const bytes = new TextEncoder().encode(text); @@ -64,6 +47,13 @@ export const webPlatform: Platform = { inspectCustom: undefined, + + isLogEnabled(name: 'api' | 'channel') { + return false; + }, + + log(name: 'api' | 'channel', message: string | Error | object) {}, + path: () => { throw new Error('Path module is not available'); }, @@ -72,3 +62,31 @@ export const webPlatform: Platform = { ws: (url: string) => new WebSocket(url), }; + +export const emptyPlatform: Platform = { + calculateSha1: async () => { + throw new Error('Not implemented'); + }, + + createGuid: () => { + throw new Error('Not implemented'); + }, + + fs: () => { + throw new Error('Not implemented'); + }, + + inspectCustom: undefined, + + isLogEnabled(name: 'api' | 'channel') { + return false; + }, + + log(name: 'api' | 'channel', message: string | Error | object) { }, + + path: () => { + throw new Error('Function not implemented.'); + }, + + pathSeparator: '/' +}; diff --git a/packages/playwright-core/src/inProcessFactory.ts b/packages/playwright-core/src/inProcessFactory.ts index 784bfc4c88..81b40afe19 100644 --- a/packages/playwright-core/src/inProcessFactory.ts +++ b/packages/playwright-core/src/inProcessFactory.ts @@ -21,13 +21,21 @@ import { BrowserServerLauncherImpl } from './browserServerImpl'; import { Connection } from './client/connection'; import { DispatcherConnection, PlaywrightDispatcher, RootDispatcher, createPlaywright } from './server'; import { setLibraryStackPrefix } from './utils/isomorphic/stackTrace'; +import { setDebugMode } from './utils/isomorphic/debug'; +import { getFromENV } from './server/utils/env'; +import { nodePlatform } from './server/utils/nodePlatform'; +import { setPlatformForSelectors } from './client/selectors'; import type { Playwright as PlaywrightAPI } from './client/playwright'; import type { Language } from './utils'; -import type { Platform } from './utils/platform'; +import type { Platform } from './common/platform'; + export function createInProcessPlaywright(platform: Platform): PlaywrightAPI { const playwright = createPlaywright({ sdkLanguage: (process.env.PW_LANG_NAME as Language | undefined) || 'javascript' }); + setDebugMode(getFromENV('PWDEBUG') || ''); + setPlatformForSelectors(nodePlatform); + setLibraryStackPrefix(path.join(__dirname, '..')); const clientConnection = new Connection(undefined, platform, undefined, []); diff --git a/packages/playwright-core/src/inprocess.ts b/packages/playwright-core/src/inprocess.ts index c057f7b5c0..fc0550e924 100644 --- a/packages/playwright-core/src/inprocess.ts +++ b/packages/playwright-core/src/inprocess.ts @@ -15,6 +15,6 @@ */ import { createInProcessPlaywright } from './inProcessFactory'; -import { nodePlatform } from './utils/platform'; +import { nodePlatform } from './server/utils/nodePlatform'; module.exports = createInProcessPlaywright(nodePlatform); diff --git a/packages/playwright-core/src/outofprocess.ts b/packages/playwright-core/src/outofprocess.ts index 8dcb8fa45a..c24decb900 100644 --- a/packages/playwright-core/src/outofprocess.ts +++ b/packages/playwright-core/src/outofprocess.ts @@ -20,7 +20,7 @@ import * as path from 'path'; import { Connection } from './client/connection'; import { PipeTransport } from './utils/pipeTransport'; import { ManualPromise } from './utils/isomorphic/manualPromise'; -import { nodePlatform } from './utils/platform'; +import { nodePlatform } from './server/utils/nodePlatform'; import type { Playwright } from './client/playwright'; diff --git a/packages/playwright-core/src/remote/playwrightConnection.ts b/packages/playwright-core/src/remote/playwrightConnection.ts index e276873668..00ca33b353 100644 --- a/packages/playwright-core/src/remote/playwrightConnection.ts +++ b/packages/playwright-core/src/remote/playwrightConnection.ts @@ -23,7 +23,7 @@ import { serverSideCallMetadata } from '../server/instrumentation'; import { assert, isUnderTest } from '../utils'; import { startProfiling, stopProfiling } from '../server/utils/profiler'; import { monotonicTime } from '../utils'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from '../server/utils/debugLogger'; import type { DispatcherScope, Playwright } from '../server'; import type { LaunchOptions } from '../server/types'; diff --git a/packages/playwright-core/src/remote/playwrightServer.ts b/packages/playwright-core/src/remote/playwrightServer.ts index 911fa1b97c..7f6a58a0a5 100644 --- a/packages/playwright-core/src/remote/playwrightServer.ts +++ b/packages/playwright-core/src/remote/playwrightServer.ts @@ -16,11 +16,11 @@ import { PlaywrightConnection } from './playwrightConnection'; import { createPlaywright } from '../server/playwright'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from '../server/utils/debugLogger'; import { Semaphore } from '../utils/isomorphic/semaphore'; import { WSServer } from '../server/utils/wsServer'; import { wrapInASCIIBox } from '../server/utils/ascii'; -import { getPlaywrightVersion } from '../utils/userAgent'; +import { getPlaywrightVersion } from '../server/utils/userAgent'; import type { ClientType } from './playwrightConnection'; import type { SocksProxy } from '../server/utils/socksProxy'; diff --git a/packages/playwright-core/src/server/android/DEPS.list b/packages/playwright-core/src/server/android/DEPS.list index b45c3a16a7..b852561b95 100644 --- a/packages/playwright-core/src/server/android/DEPS.list +++ b/packages/playwright-core/src/server/android/DEPS.list @@ -3,6 +3,7 @@ ../../common/ ../../protocol/ ../../utils/ +../../utils/isomorphic/ ../../utilsBundle.ts ../chromium/ ../utils diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts index 68db8ab77c..c1516dea76 100644 --- a/packages/playwright-core/src/server/android/android.ts +++ b/packages/playwright-core/src/server/android/android.ts @@ -19,13 +19,13 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { TimeoutSettings } from '../../common/timeoutSettings'; +import { TimeoutSettings } from '../../utils/isomorphic/timeoutSettings'; import { PipeTransport } from '../../utils/pipeTransport'; import { createGuid } from '../utils/crypto'; -import { isUnderTest } from '../../utils/debug'; -import { getPackageManagerExecCommand } from '../../utils/env'; +import { isUnderTest } from '../../utils/isomorphic/debug'; +import { getPackageManagerExecCommand } from '../utils/env'; import { makeWaitForNextTask } from '../../utils/task'; -import { RecentLogsCollector } from '../../utils/debugLogger'; +import { RecentLogsCollector } from '../utils/debugLogger'; import { debug } from '../../utilsBundle'; import { wsReceiver, wsSender } from '../../utilsBundle'; import { validateBrowserContextOptions } from '../browserContext'; diff --git a/packages/playwright-core/src/server/android/backendAdb.ts b/packages/playwright-core/src/server/android/backendAdb.ts index 737d415050..036c74703e 100644 --- a/packages/playwright-core/src/server/android/backendAdb.ts +++ b/packages/playwright-core/src/server/android/backendAdb.ts @@ -17,7 +17,7 @@ import { EventEmitter } from 'events'; import * as net from 'net'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { createGuid } from '../utils/crypto'; import { debug } from '../../utilsBundle'; diff --git a/packages/playwright-core/src/server/bidi/bidiConnection.ts b/packages/playwright-core/src/server/bidi/bidiConnection.ts index 87b3f59c9b..0882836c38 100644 --- a/packages/playwright-core/src/server/bidi/bidiConnection.ts +++ b/packages/playwright-core/src/server/bidi/bidiConnection.ts @@ -16,11 +16,11 @@ import { EventEmitter } from 'events'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { helper } from '../helper'; import { ProtocolError } from '../protocolError'; -import type { RecentLogsCollector } from '../../utils/debugLogger'; +import type { RecentLogsCollector } from '../utils/debugLogger'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { ProtocolLogger } from '../types'; import type * as bidiCommands from './third_party/bidiCommands'; diff --git a/packages/playwright-core/src/server/bidi/bidiOverCdp.ts b/packages/playwright-core/src/server/bidi/bidiOverCdp.ts index adf7c9afbf..8acd45563d 100644 --- a/packages/playwright-core/src/server/bidi/bidiOverCdp.ts +++ b/packages/playwright-core/src/server/bidi/bidiOverCdp.ts @@ -17,7 +17,7 @@ import * as bidiMapper from 'chromium-bidi/lib/cjs/bidiMapper/BidiMapper'; import * as bidiCdpConnection from 'chromium-bidi/lib/cjs/cdp/CdpConnection'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { ChromiumBidi } from 'chromium-bidi/lib/cjs/protocol/protocol'; diff --git a/packages/playwright-core/src/server/browser.ts b/packages/playwright-core/src/server/browser.ts index d99a3f8f8a..7cf00f73c8 100644 --- a/packages/playwright-core/src/server/browser.ts +++ b/packages/playwright-core/src/server/browser.ts @@ -24,7 +24,7 @@ import { ClientCertificatesProxy } from './socksClientCertificatesInterceptor'; import type { CallMetadata } from './instrumentation'; import type * as types from './types'; import type { ProxySettings } from './types'; -import type { RecentLogsCollector } from '../utils/debugLogger'; +import type { RecentLogsCollector } from './utils/debugLogger'; import type * as channels from '@protocol/channels'; import type { ChildProcess } from 'child_process'; diff --git a/packages/playwright-core/src/server/browserContext.ts b/packages/playwright-core/src/server/browserContext.ts index 48c87f7dc4..fd50994343 100644 --- a/packages/playwright-core/src/server/browserContext.ts +++ b/packages/playwright-core/src/server/browserContext.ts @@ -18,9 +18,9 @@ import * as fs from 'fs'; import * as path from 'path'; -import { TimeoutSettings } from '../common/timeoutSettings'; +import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { createGuid } from './utils/crypto'; -import { debugMode } from '../utils/debug'; +import { debugMode } from '../utils/isomorphic/debug'; import { Clock } from './clock'; import { Debugger } from './debugger'; import { BrowserContextAPIRequestContext } from './fetch'; diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index 9952aef2f4..7fe3844c7d 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -19,7 +19,7 @@ import * as os from 'os'; import * as path from 'path'; import { normalizeProxySettings, validateBrowserContextOptions } from './browserContext'; -import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings'; +import { DEFAULT_TIMEOUT, TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { ManualPromise, assert, debugMode } from '../utils'; import { existsAsync } from './utils/fileUtils'; import { helper } from './helper'; @@ -31,7 +31,7 @@ import { isProtocolError } from './protocolError'; import { registry } from './registry'; import { ClientCertificatesProxy } from './socksClientCertificatesInterceptor'; import { WebSocketTransport } from './transport'; -import { RecentLogsCollector } from '../utils/debugLogger'; +import { RecentLogsCollector } from './utils/debugLogger'; import type { Browser, BrowserOptions, BrowserProcess } from './browser'; import type { BrowserContext } from './browserContext'; diff --git a/packages/playwright-core/src/server/chromium/chromium.ts b/packages/playwright-core/src/server/chromium/chromium.ts index 7c520aa213..3f06e135cd 100644 --- a/packages/playwright-core/src/server/chromium/chromium.ts +++ b/packages/playwright-core/src/server/chromium/chromium.ts @@ -22,13 +22,13 @@ import * as path from 'path'; import { chromiumSwitches } from './chromiumSwitches'; import { CRBrowser } from './crBrowser'; import { kBrowserCloseMessageId } from './crConnection'; -import { TimeoutSettings } from '../../common/timeoutSettings'; +import { TimeoutSettings } from '../../utils/isomorphic/timeoutSettings'; import { debugMode, headersArrayToObject, headersObjectToArray, } from '../../utils'; import { wrapInASCIIBox } from '../utils/ascii'; -import { RecentLogsCollector } from '../../utils/debugLogger'; +import { RecentLogsCollector } from '../utils/debugLogger'; import { ManualPromise } from '../../utils/isomorphic/manualPromise'; import { fetchData } from '../utils/network'; -import { getUserAgent } from '../../utils/userAgent'; +import { getUserAgent } from '../utils/userAgent'; import { validateBrowserContextOptions } from '../browserContext'; import { BrowserType, kNoXServerRunningError } from '../browserType'; import { BrowserReadyState } from '../browserType'; diff --git a/packages/playwright-core/src/server/chromium/crBrowser.ts b/packages/playwright-core/src/server/chromium/crBrowser.ts index abd4aee685..7cc6030486 100644 --- a/packages/playwright-core/src/server/chromium/crBrowser.ts +++ b/packages/playwright-core/src/server/chromium/crBrowser.ts @@ -17,7 +17,7 @@ import * as path from 'path'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { createGuid } from '../utils/crypto'; import { Artifact } from '../artifact'; import { Browser } from '../browser'; diff --git a/packages/playwright-core/src/server/chromium/crConnection.ts b/packages/playwright-core/src/server/chromium/crConnection.ts index 424d64a500..98c566c82a 100644 --- a/packages/playwright-core/src/server/chromium/crConnection.ts +++ b/packages/playwright-core/src/server/chromium/crConnection.ts @@ -18,14 +18,14 @@ import { EventEmitter } from 'events'; import { assert, eventsHelper } from '../../utils'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { helper } from '../helper'; import { ProtocolError } from '../protocolError'; import type { RegisteredListener } from '../../utils'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { Protocol } from './protocol'; -import type { RecentLogsCollector } from '../../utils/debugLogger'; +import type { RecentLogsCollector } from '../utils/debugLogger'; import type { ProtocolLogger } from '../types'; diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index bb218202e6..34470470dc 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -17,7 +17,7 @@ import * as path from 'path'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { createGuid } from '../utils/crypto'; import { eventsHelper } from '../utils/eventsHelper'; import { rewriteErrorMessage } from '../../utils/isomorphic/stackTrace'; diff --git a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts index 37ff8c8b81..b582aa8788 100644 --- a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts @@ -16,9 +16,9 @@ import { Dispatcher } from './dispatcher'; import { SdkObject } from '../../server/instrumentation'; -import * as localUtils from '../../utils/localUtils'; -import { nodePlatform } from '../../utils/platform'; -import { getUserAgent } from '../../utils/userAgent'; +import * as localUtils from '../../common/localUtils'; +import { nodePlatform } from '../utils/nodePlatform'; +import { getUserAgent } from '../utils/userAgent'; import { deviceDescriptors as descriptors } from '../deviceDescriptors'; import { JsonPipeDispatcher } from '../dispatchers/jsonPipeDispatcher'; import { Progress, ProgressController } from '../progress'; @@ -26,7 +26,7 @@ import { SocksInterceptor } from '../socksInterceptor'; import { WebSocketTransport } from '../transport'; import { fetchData } from '../utils/network'; -import type { HarBackend } from '../../utils/harBackend'; +import type { HarBackend } from '../../common/harBackend'; import type { CallMetadata } from '../instrumentation'; import type { Playwright } from '../playwright'; import type { RootDispatcher } from './dispatcher'; diff --git a/packages/playwright-core/src/server/electron/DEPS.list b/packages/playwright-core/src/server/electron/DEPS.list index 1d51da425e..1acb5c5a0e 100644 --- a/packages/playwright-core/src/server/electron/DEPS.list +++ b/packages/playwright-core/src/server/electron/DEPS.list @@ -2,5 +2,6 @@ ../ ../../common/ ../../utils/ +../../utils/isomorphic/ ../chromium/ ../utils \ No newline at end of file diff --git a/packages/playwright-core/src/server/electron/electron.ts b/packages/playwright-core/src/server/electron/electron.ts index 1728a317a8..4713324ed1 100644 --- a/packages/playwright-core/src/server/electron/electron.ts +++ b/packages/playwright-core/src/server/electron/electron.ts @@ -19,10 +19,10 @@ import * as os from 'os'; import * as path from 'path'; import * as readline from 'readline'; -import { TimeoutSettings } from '../../common/timeoutSettings'; +import { TimeoutSettings } from '../../utils/isomorphic/timeoutSettings'; import { ManualPromise } from '../../utils'; import { wrapInASCIIBox } from '../utils/ascii'; -import { RecentLogsCollector } from '../../utils/debugLogger'; +import { RecentLogsCollector } from '../utils/debugLogger'; import { eventsHelper } from '../utils/eventsHelper'; import { validateBrowserContextOptions } from '../browserContext'; import { CRBrowser } from '../chromium/crBrowser'; diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 08e63bb83b..6e1d6d02f1 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -21,10 +21,10 @@ import { TLSSocket } from 'tls'; import * as url from 'url'; import * as zlib from 'zlib'; -import { TimeoutSettings } from '../common/timeoutSettings'; +import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { assert, constructURLBasedOnBaseURL, eventsHelper, monotonicTime } from '../utils'; import { createGuid } from './utils/crypto'; -import { getUserAgent } from '../utils/userAgent'; +import { getUserAgent } from './utils/userAgent'; import { HttpsProxyAgent, SocksProxyAgent } from '../utilsBundle'; import { BrowserContext, verifyClientCertificates } from './browserContext'; import { CookieStore, domainMatches, parseRawCookie } from './cookieStore'; diff --git a/packages/playwright-core/src/server/fileUploadUtils.ts b/packages/playwright-core/src/server/fileUploadUtils.ts index 1c53812a0a..908e7644ac 100644 --- a/packages/playwright-core/src/server/fileUploadUtils.ts +++ b/packages/playwright-core/src/server/fileUploadUtils.ts @@ -17,8 +17,8 @@ import * as fs from 'fs'; import * as path from 'path'; -import { assert } from '../utils/debug'; -import { fileUploadSizeLimit } from '../utils/fileUtils'; +import { assert } from '../utils/isomorphic/debug'; +import { fileUploadSizeLimit } from '../common/fileUtils'; import { mime } from '../utilsBundle'; import type { WritableStreamDispatcher } from './dispatchers/writableStreamDispatcher'; diff --git a/packages/playwright-core/src/server/firefox/ffConnection.ts b/packages/playwright-core/src/server/firefox/ffConnection.ts index 6001754219..1477ace249 100644 --- a/packages/playwright-core/src/server/firefox/ffConnection.ts +++ b/packages/playwright-core/src/server/firefox/ffConnection.ts @@ -17,13 +17,13 @@ import { EventEmitter } from 'events'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { helper } from '../helper'; import { ProtocolError } from '../protocolError'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { Protocol } from './protocol'; -import type { RecentLogsCollector } from '../../utils/debugLogger'; +import type { RecentLogsCollector } from '../utils/debugLogger'; import type { ProtocolLogger } from '../types'; diff --git a/packages/playwright-core/src/server/firefox/ffPage.ts b/packages/playwright-core/src/server/firefox/ffPage.ts index c2b59ca08b..22229dff3e 100644 --- a/packages/playwright-core/src/server/firefox/ffPage.ts +++ b/packages/playwright-core/src/server/firefox/ffPage.ts @@ -25,7 +25,7 @@ import { FFSession } from './ffConnection'; import { FFExecutionContext } from './ffExecutionContext'; import { RawKeyboardImpl, RawMouseImpl, RawTouchscreenImpl } from './ffInput'; import { FFNetworkManager } from './ffNetworkManager'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { splitErrorMessage } from '../../utils/isomorphic/stackTrace'; import { BrowserContext } from '../browserContext'; import { TargetClosedError } from '../errors'; diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 87bd4f9623..dee2ad7f08 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -29,7 +29,7 @@ import { ProgressController } from './progress'; import * as types from './types'; import { LongStandingScope, asLocator, assert, compressCallLog, constructURLBasedOnBaseURL, makeWaitForNextTask, monotonicTime } from '../utils'; import { isSessionClosedError } from './protocolError'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from './utils/debugLogger'; import { eventsHelper } from './utils/eventsHelper'; import { isInvalidSelectorError } from '../utils/isomorphic/selectorParser'; import { ManualPromise } from '../utils/isomorphic/manualPromise'; diff --git a/packages/playwright-core/src/server/helper.ts b/packages/playwright-core/src/server/helper.ts index da049e2be6..e9fec62419 100644 --- a/packages/playwright-core/src/server/helper.ts +++ b/packages/playwright-core/src/server/helper.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from './utils/debugLogger'; import { eventsHelper } from './utils/eventsHelper'; import type { Progress } from './progress'; diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 300cf05e50..d2db2e4211 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -28,12 +28,12 @@ import { parseEvaluationResultValue, source } from './isomorphic/utilityScriptSe import * as js from './javascript'; import { ProgressController } from './progress'; import { Screenshotter, validateScreenshotOptions } from './screenshotter'; -import { TimeoutSettings } from '../common/timeoutSettings'; +import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { LongStandingScope, assert, compressCallLog, trimStringWithEllipsis } from '../utils'; import { createGuid } from './utils/crypto'; import { asLocator } from '../utils'; import { getComparator } from './utils/comparators'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from './utils/debugLogger'; import { isInvalidSelectorError } from '../utils/isomorphic/selectorParser'; import { ManualPromise } from '../utils/isomorphic/manualPromise'; diff --git a/packages/playwright-core/src/server/pipeTransport.ts b/packages/playwright-core/src/server/pipeTransport.ts index 67bf126324..ba811e606e 100644 --- a/packages/playwright-core/src/server/pipeTransport.ts +++ b/packages/playwright-core/src/server/pipeTransport.ts @@ -16,7 +16,7 @@ */ import { makeWaitForNextTask } from '../utils'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from './utils/debugLogger'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from './transport'; diff --git a/packages/playwright-core/src/server/progress.ts b/packages/playwright-core/src/server/progress.ts index 9766c66ebd..30db144fbb 100644 --- a/packages/playwright-core/src/server/progress.ts +++ b/packages/playwright-core/src/server/progress.ts @@ -20,7 +20,7 @@ import { ManualPromise } from '../utils/isomorphic/manualPromise'; import type { CallMetadata, Instrumentation, SdkObject } from './instrumentation'; import type { Progress as CommonProgress } from '../common/progress'; -import type { LogName } from '../utils/debugLogger'; +import type { LogName } from './utils/debugLogger'; export interface Progress extends CommonProgress { metadata: CallMetadata; diff --git a/packages/playwright-core/src/server/recorder/recorderCollection.ts b/packages/playwright-core/src/server/recorder/recorderCollection.ts index 454fa05b90..8c7b344b8e 100644 --- a/packages/playwright-core/src/server/recorder/recorderCollection.ts +++ b/packages/playwright-core/src/server/recorder/recorderCollection.ts @@ -18,7 +18,7 @@ import { EventEmitter } from 'events'; import { performAction } from './recorderRunner'; import { collapseActions } from './recorderUtils'; -import { isUnderTest } from '../../utils/debug'; +import { isUnderTest } from '../../utils/isomorphic/debug'; import { monotonicTime } from '../../utils/isomorphic/time'; import type { Signal } from '../../../../recorder/src/actions'; diff --git a/packages/playwright-core/src/server/registry/browserFetcher.ts b/packages/playwright-core/src/server/registry/browserFetcher.ts index 0e7809cadb..fb6afb3f10 100644 --- a/packages/playwright-core/src/server/registry/browserFetcher.ts +++ b/packages/playwright-core/src/server/registry/browserFetcher.ts @@ -20,9 +20,9 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { ManualPromise } from '../../utils/isomorphic/manualPromise'; -import { getUserAgent } from '../../utils/userAgent'; +import { getUserAgent } from '../utils/userAgent'; import { progress as ProgressBar } from '../../utilsBundle'; import { colors } from '../../utils/isomorphic/colors'; import { existsAsync } from '../utils/fileUtils'; diff --git a/packages/playwright-core/src/server/registry/dependencies.ts b/packages/playwright-core/src/server/registry/dependencies.ts index e405d75c6f..5cf4a097b1 100644 --- a/packages/playwright-core/src/server/registry/dependencies.ts +++ b/packages/playwright-core/src/server/registry/dependencies.ts @@ -21,9 +21,9 @@ import * as path from 'path'; import { deps } from './nativeDeps'; import { wrapInASCIIBox } from '../utils/ascii'; -import { hostPlatform, isOfficiallySupportedPlatform } from '../../utils/hostPlatform'; +import { hostPlatform, isOfficiallySupportedPlatform } from '../utils/hostPlatform'; import { spawnAsync } from '../utils/spawnAsync'; -import { getPlaywrightVersion } from '../../utils/userAgent'; +import { getPlaywrightVersion } from '../utils/userAgent'; import { buildPlaywrightCLICommand, registry } from '.'; diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 87804f06dd..e0282120fb 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -25,16 +25,16 @@ import { dockerVersion, readDockerVersionSync, transformCommandsForRoot } from ' import { installDependenciesLinux, installDependenciesWindows, validateDependenciesLinux, validateDependenciesWindows } from './dependencies'; import { calculateSha1, getAsBooleanFromENV, getFromENV, getPackageManagerExecCommand } from '../../utils'; import { wrapInASCIIBox } from '../utils/ascii'; -import { debugLogger } from '../../utils/debugLogger'; -import { hostPlatform, isOfficiallySupportedPlatform } from '../../utils/hostPlatform'; +import { debugLogger } from '../utils/debugLogger'; +import { hostPlatform, isOfficiallySupportedPlatform } from '../utils/hostPlatform'; import { fetchData } from '../utils/network'; import { spawnAsync } from '../utils/spawnAsync'; -import { getEmbedderName } from '../../utils/userAgent'; +import { getEmbedderName } from '../utils/userAgent'; import { lockfile } from '../../utilsBundle'; import { canAccessFile, existsAsync, removeFolders } from '../utils/fileUtils'; import type { DependencyGroup } from './dependencies'; -import type { HostPlatform } from '../../utils/hostPlatform'; +import type { HostPlatform } from '../utils/hostPlatform'; export { writeDockerVersion } from './dependencies'; diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index b1943ca123..f769f60d74 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -24,7 +24,7 @@ import { SocksProxy } from './utils/socksProxy'; import { ManualPromise, escapeHTML, generateSelfSignedCertificate, rewriteErrorMessage } from '../utils'; import { verifyClientCertificates } from './browserContext'; import { createProxyAgent } from './fetch'; -import { debugLogger } from '../utils/debugLogger'; +import { debugLogger } from './utils/debugLogger'; import { createSocket, createTLSSocket } from './utils/happyEyeballs'; import type * as types from './types'; diff --git a/packages/playwright-core/src/server/trace/recorder/snapshotter.ts b/packages/playwright-core/src/server/trace/recorder/snapshotter.ts index 9a914e1ad4..f4e288d077 100644 --- a/packages/playwright-core/src/server/trace/recorder/snapshotter.ts +++ b/packages/playwright-core/src/server/trace/recorder/snapshotter.ts @@ -17,7 +17,7 @@ import { frameSnapshotStreamer } from './snapshotterInjected'; import { monotonicTime } from '../../../utils/isomorphic/time'; import { calculateSha1, createGuid } from '../../utils/crypto'; -import { debugLogger } from '../../../utils/debugLogger'; +import { debugLogger } from '../../utils/debugLogger'; import { eventsHelper } from '../../utils/eventsHelper'; import { mime } from '../../../utilsBundle'; import { BrowserContext } from '../../browserContext'; diff --git a/packages/playwright-core/src/server/trace/recorder/tracing.ts b/packages/playwright-core/src/server/trace/recorder/tracing.ts index 26e3075a29..309867f3b0 100644 --- a/packages/playwright-core/src/server/trace/recorder/tracing.ts +++ b/packages/playwright-core/src/server/trace/recorder/tracing.ts @@ -20,7 +20,7 @@ import * as path from 'path'; import { Snapshotter } from './snapshotter'; import { commandsWithTracingSnapshots } from '../../../protocol/debug'; -import { assert } from '../../../utils/debug'; +import { assert } from '../../../utils/isomorphic/debug'; import { monotonicTime } from '../../../utils/isomorphic/time'; import { eventsHelper } from '../../utils/eventsHelper'; import { createGuid } from '../../utils/crypto'; diff --git a/packages/playwright-core/src/server/utils/DEPS.list b/packages/playwright-core/src/server/utils/DEPS.list index 8d1b7a30f2..685e00df46 100644 --- a/packages/playwright-core/src/server/utils/DEPS.list +++ b/packages/playwright-core/src/server/utils/DEPS.list @@ -1,4 +1,5 @@ [*] +../../common ../../utils ../../utils/isomorphic ../../utilsBundle.ts diff --git a/packages/playwright-core/src/server/utils/crypto.ts b/packages/playwright-core/src/server/utils/crypto.ts index 0a35c3c8c9..7189f38b00 100644 --- a/packages/playwright-core/src/server/utils/crypto.ts +++ b/packages/playwright-core/src/server/utils/crypto.ts @@ -16,7 +16,7 @@ import * as crypto from 'crypto'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; export function createGuid(): string { return crypto.randomBytes(16).toString('hex'); diff --git a/packages/playwright-core/src/utils/debugLogger.ts b/packages/playwright-core/src/server/utils/debugLogger.ts similarity index 98% rename from packages/playwright-core/src/utils/debugLogger.ts rename to packages/playwright-core/src/server/utils/debugLogger.ts index 24b0a1dbf8..8713b3cf7e 100644 --- a/packages/playwright-core/src/utils/debugLogger.ts +++ b/packages/playwright-core/src/server/utils/debugLogger.ts @@ -16,7 +16,7 @@ import * as fs from 'fs'; -import { debug } from '../utilsBundle'; +import { debug } from '../../utilsBundle'; const debugLoggerColorMap = { 'api': 45, // cyan diff --git a/packages/playwright-core/src/utils/env.ts b/packages/playwright-core/src/server/utils/env.ts similarity index 100% rename from packages/playwright-core/src/utils/env.ts rename to packages/playwright-core/src/server/utils/env.ts diff --git a/packages/playwright-core/src/server/utils/happyEyeballs.ts b/packages/playwright-core/src/server/utils/happyEyeballs.ts index a5c6087513..da3481f4c1 100644 --- a/packages/playwright-core/src/server/utils/happyEyeballs.ts +++ b/packages/playwright-core/src/server/utils/happyEyeballs.ts @@ -20,7 +20,7 @@ import * as https from 'https'; import * as net from 'net'; import * as tls from 'tls'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { ManualPromise } from '../../utils/isomorphic/manualPromise'; import { monotonicTime } from '../../utils/isomorphic/time'; diff --git a/packages/playwright-core/src/utils/hostPlatform.ts b/packages/playwright-core/src/server/utils/hostPlatform.ts similarity index 100% rename from packages/playwright-core/src/utils/hostPlatform.ts rename to packages/playwright-core/src/server/utils/hostPlatform.ts diff --git a/packages/playwright-core/src/server/utils/httpServer.ts b/packages/playwright-core/src/server/utils/httpServer.ts index 21992195c0..0c9f0fe25a 100644 --- a/packages/playwright-core/src/server/utils/httpServer.ts +++ b/packages/playwright-core/src/server/utils/httpServer.ts @@ -19,7 +19,7 @@ import * as path from 'path'; import { mime, wsServer } from '../../utilsBundle'; import { createGuid } from './crypto'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { ManualPromise } from '../../utils/isomorphic/manualPromise'; import { createHttpServer } from './network'; diff --git a/packages/playwright-core/src/utils/linuxUtils.ts b/packages/playwright-core/src/server/utils/linuxUtils.ts similarity index 73% rename from packages/playwright-core/src/utils/linuxUtils.ts rename to packages/playwright-core/src/server/utils/linuxUtils.ts index c51d32f9d5..3c85ebe091 100644 --- a/packages/playwright-core/src/utils/linuxUtils.ts +++ b/packages/playwright-core/src/server/utils/linuxUtils.ts @@ -23,26 +23,6 @@ let osRelease: { version: string, } | undefined; -export async function getLinuxDistributionInfo(): Promise<{ id: string, version: string } | undefined> { - if (process.platform !== 'linux') - return undefined; - if (!osRelease && !didFailToReadOSRelease) { - try { - // List of /etc/os-release values for different distributions could be - // found here: https://gist.github.com/aslushnikov/8ceddb8288e4cf9db3039c02e0f4fb75 - const osReleaseText = await fs.promises.readFile('/etc/os-release', 'utf8'); - const fields = parseOSReleaseText(osReleaseText); - osRelease = { - id: fields.get('id') ?? '', - version: fields.get('version_id') ?? '', - }; - } catch (e) { - didFailToReadOSRelease = true; - } - } - return osRelease; -} - export function getLinuxDistributionInfoSync(): { id: string, version: string } | undefined { if (process.platform !== 'linux') return undefined; diff --git a/packages/playwright-core/src/server/utils/nodePlatform.ts b/packages/playwright-core/src/server/utils/nodePlatform.ts new file mode 100644 index 0000000000..1a6f2ddc25 --- /dev/null +++ b/packages/playwright-core/src/server/utils/nodePlatform.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as crypto from 'crypto'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as util from 'util'; + +import { Platform } from '../../common/platform'; +import { debugLogger } from './debugLogger'; + +export const nodePlatform: Platform = { + calculateSha1: (text: string) => { + const sha1 = crypto.createHash('sha1'); + sha1.update(text); + return Promise.resolve(sha1.digest('hex')); + }, + + createGuid: () => crypto.randomBytes(16).toString('hex'), + + fs: () => fs, + + inspectCustom: util.inspect.custom, + + isLogEnabled(name: 'api' | 'channel') { + return debugLogger.isEnabled(name); + }, + + log(name: 'api' | 'channel', message: string | Error | object) { + debugLogger.log(name, message); + }, + + path: () => path, + + pathSeparator: path.sep +}; diff --git a/packages/playwright-core/src/server/utils/socksProxy.ts b/packages/playwright-core/src/server/utils/socksProxy.ts index 49dab675f6..c0fe0f126a 100644 --- a/packages/playwright-core/src/server/utils/socksProxy.ts +++ b/packages/playwright-core/src/server/utils/socksProxy.ts @@ -17,9 +17,9 @@ import EventEmitter from 'events'; import * as net from 'net'; -import { assert } from '../../utils/debug'; +import { assert } from '../../utils/isomorphic/debug'; import { createGuid } from './crypto'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from './debugLogger'; import { createSocket } from './happyEyeballs'; import type { AddressInfo } from 'net'; diff --git a/packages/playwright-core/src/utils/userAgent.ts b/packages/playwright-core/src/server/utils/userAgent.ts similarity index 98% rename from packages/playwright-core/src/utils/userAgent.ts rename to packages/playwright-core/src/server/utils/userAgent.ts index 7f3e3d2275..9676a5bae5 100644 --- a/packages/playwright-core/src/utils/userAgent.ts +++ b/packages/playwright-core/src/server/utils/userAgent.ts @@ -77,6 +77,6 @@ export function getEmbedderName(): { embedderName: string, embedderVersion: stri } export function getPlaywrightVersion(majorMinorOnly = false): string { - const version = process.env.PW_VERSION_OVERRIDE || require('./../../package.json').version; + const version = process.env.PW_VERSION_OVERRIDE || require('./../../../package.json').version; return majorMinorOnly ? version.split('.').slice(0, 2).join('.') : version; } diff --git a/packages/playwright-core/src/server/utils/wsServer.ts b/packages/playwright-core/src/server/utils/wsServer.ts index b223802a1b..68362f14de 100644 --- a/packages/playwright-core/src/server/utils/wsServer.ts +++ b/packages/playwright-core/src/server/utils/wsServer.ts @@ -16,7 +16,7 @@ import { createHttpServer } from './network'; import { wsServer } from '../../utilsBundle'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from './debugLogger'; import type { WebSocket, WebSocketServer } from '../../utilsBundle'; import type http from 'http'; diff --git a/packages/playwright-core/src/server/webkit/wkConnection.ts b/packages/playwright-core/src/server/webkit/wkConnection.ts index 0012d8702f..ada50a413b 100644 --- a/packages/playwright-core/src/server/webkit/wkConnection.ts +++ b/packages/playwright-core/src/server/webkit/wkConnection.ts @@ -18,13 +18,13 @@ import { EventEmitter } from 'events'; import { assert } from '../../utils'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import { helper } from '../helper'; import { ProtocolError } from '../protocolError'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { Protocol } from './protocol'; -import type { RecentLogsCollector } from '../../utils/debugLogger'; +import type { RecentLogsCollector } from '../utils/debugLogger'; import type { ProtocolLogger } from '../types'; diff --git a/packages/playwright-core/src/server/webkit/wkPage.ts b/packages/playwright-core/src/server/webkit/wkPage.ts index 91a5054123..f9e9517fb2 100644 --- a/packages/playwright-core/src/server/webkit/wkPage.ts +++ b/packages/playwright-core/src/server/webkit/wkPage.ts @@ -21,7 +21,7 @@ import { assert, debugAssert } from '../../utils'; import { headersArrayToObject } from '../../utils/isomorphic/headers'; import { createGuid } from '../utils/crypto'; import { eventsHelper } from '../utils/eventsHelper'; -import { hostPlatform } from '../../utils/hostPlatform'; +import { hostPlatform } from '../utils/hostPlatform'; import { splitErrorMessage } from '../../utils/isomorphic/stackTrace'; import { PNG, jpegjs } from '../../utilsBundle'; import { BrowserContext } from '../browserContext'; @@ -39,7 +39,7 @@ import { RawKeyboardImpl, RawMouseImpl, RawTouchscreenImpl } from './wkInput'; import { WKInterceptableRequest, WKRouteImpl } from './wkInterceptableRequest'; import { WKProvisionalPage } from './wkProvisionalPage'; import { WKWorkers } from './wkWorkers'; -import { debugLogger } from '../../utils/debugLogger'; +import { debugLogger } from '../utils/debugLogger'; import type { Protocol } from './protocol'; import type { WKBrowserContext } from './wkBrowser'; diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index 62058f3451..b4829cb78c 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -15,6 +15,7 @@ */ export * from './utils/isomorphic/colors'; +export * from './utils/isomorphic/debug'; export * from './utils/isomorphic/locatorGenerators'; export * from './utils/isomorphic/manualPromise'; export * from './utils/isomorphic/mimeType'; @@ -25,29 +26,27 @@ export * from './utils/isomorphic/time'; export * from './utils/isomorphic/timeoutRunner'; export * from './utils/isomorphic/urlMatch'; -export * from './utils/debug'; -export * from './utils/debugLogger'; -export * from './utils/env'; -export * from './utils/hostPlatform'; export * from './utils/isomorphic/headers'; export * from './utils/isomorphic/semaphore'; -export * from './utils/platform'; export * from './utils/isomorphic/stackTrace'; export * from './utils/task'; -export * from './utils/userAgent'; export * from './utils/zipFile'; export * from './utils/zones'; export * from './server/utils/ascii'; export * from './server/utils/comparators'; export * from './server/utils/crypto'; +export * from './server/utils/debugLogger'; +export * from './server/utils/env'; export * from './server/utils/eventsHelper'; export * from './server/utils/expectUtils'; export * from './server/utils/fileUtils'; +export * from './server/utils/hostPlatform'; export * from './server/utils/httpServer'; export * from './server/utils/network'; export * from './server/utils/processLauncher'; export * from './server/utils/profiler'; export * from './server/utils/socksProxy'; export * from './server/utils/spawnAsync'; +export * from './server/utils/userAgent'; export * from './server/utils/wsServer'; diff --git a/packages/playwright-core/src/utils/debug.ts b/packages/playwright-core/src/utils/isomorphic/debug.ts similarity index 83% rename from packages/playwright-core/src/utils/debug.ts rename to packages/playwright-core/src/utils/isomorphic/debug.ts index 2e199b3a31..1eec988aa9 100644 --- a/packages/playwright-core/src/utils/debug.ts +++ b/packages/playwright-core/src/utils/isomorphic/debug.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { getFromENV } from './env'; - export function assert(value: any, message?: string): asserts value { if (!value) throw new Error(message || 'Assertion error'); @@ -26,13 +24,18 @@ export function debugAssert(value: any, message?: string): asserts value { throw new Error(message); } -const debugEnv = getFromENV('PWDEBUG') || ''; +let _debugMode: string | undefined; + +export function setDebugMode(mode: string) { + _debugMode = mode; +} + export function debugMode() { - if (debugEnv === 'console') + if (_debugMode === 'console') return 'console'; - if (debugEnv === '0' || debugEnv === 'false') + if (_debugMode === '0' || _debugMode === 'false') return ''; - return debugEnv ? 'inspector' : ''; + return _debugMode ? 'inspector' : ''; } let _isUnderTest = !!process.env.PWTEST_UNDER_TEST; diff --git a/packages/playwright-core/src/common/timeoutSettings.ts b/packages/playwright-core/src/utils/isomorphic/timeoutSettings.ts similarity index 98% rename from packages/playwright-core/src/common/timeoutSettings.ts rename to packages/playwright-core/src/utils/isomorphic/timeoutSettings.ts index 65c8be1ecf..02c02a33b5 100644 --- a/packages/playwright-core/src/common/timeoutSettings.ts +++ b/packages/playwright-core/src/utils/isomorphic/timeoutSettings.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { debugMode } from '../utils'; +import { debugMode } from './debug'; export const DEFAULT_TIMEOUT = 30000; export const DEFAULT_LAUNCH_TIMEOUT = 3 * 60 * 1000; // 3 minutes diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index c0475ab57e..1298e38b5e 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -19,7 +19,7 @@ import fs from 'fs'; import type http from 'http'; import type net from 'net'; import * as path from 'path'; -import { getUserAgent, getPlaywrightVersion } from '../../packages/playwright-core/lib/utils/userAgent'; +import { getUserAgent, getPlaywrightVersion } from '../../packages/playwright-core/lib/server/utils/userAgent'; import WebSocket from 'ws'; import { expect, playwrightTest } from '../config/browserTest'; import { parseTrace, suppressCertificateWarning } from '../config/utils'; diff --git a/tests/library/capabilities.spec.ts b/tests/library/capabilities.spec.ts index 29328f3f80..8b065834ab 100644 --- a/tests/library/capabilities.spec.ts +++ b/tests/library/capabilities.spec.ts @@ -17,7 +17,7 @@ import os from 'os'; import url from 'url'; import { contextTest as it, expect } from '../config/browserTest'; -import { hostPlatform } from '../../packages/playwright-core/src/utils/hostPlatform'; +import { hostPlatform } from '../../packages/playwright-core/src/server/utils/hostPlatform'; it('SharedArrayBuffer should work @smoke', async function({ contextFactory, httpsServer }) { const context = await contextFactory({ ignoreHTTPSErrors: true }); diff --git a/tests/library/chromium/connect-over-cdp.spec.ts b/tests/library/chromium/connect-over-cdp.spec.ts index f31f60baf0..3191403be8 100644 --- a/tests/library/chromium/connect-over-cdp.spec.ts +++ b/tests/library/chromium/connect-over-cdp.spec.ts @@ -18,7 +18,7 @@ import { playwrightTest as test, expect } from '../../config/browserTest'; import http from 'http'; import fs from 'fs'; -import { getUserAgent } from '../../../packages/playwright-core/lib/utils/userAgent'; +import { getUserAgent } from '../../../packages/playwright-core/lib/server/utils/userAgent'; import { suppressCertificateWarning } from '../../config/utils'; test.skip(({ mode }) => mode === 'service2'); diff --git a/tests/library/events/check-listener-leaks.spec.ts b/tests/library/events/check-listener-leaks.spec.ts index d9b51f27ef..5a328d720f 100644 --- a/tests/library/events/check-listener-leaks.spec.ts +++ b/tests/library/events/check-listener-leaks.spec.ts @@ -22,7 +22,7 @@ import events from 'events'; import { EventEmitter } from '../../../packages/playwright-core/lib/client/eventEmitter'; -import { setUnderTest } from '../../../packages/playwright-core/lib/utils/debug'; +import { setUnderTest } from '../../../packages/playwright-core/lib/utils/isomorphic/debug'; import { test, expect } from '@playwright/test'; import * as common from './utils'; diff --git a/tests/library/global-fetch.spec.ts b/tests/library/global-fetch.spec.ts index 0ad73bb9b6..9a402ed152 100644 --- a/tests/library/global-fetch.spec.ts +++ b/tests/library/global-fetch.spec.ts @@ -16,7 +16,7 @@ import os from 'os'; import * as util from 'util'; -import { getPlaywrightVersion } from '../../packages/playwright-core/lib/utils/userAgent'; +import { getPlaywrightVersion } from '../../packages/playwright-core/lib/server/utils/userAgent'; import { expect, playwrightTest as base } from '../config/browserTest'; import { kTargetClosedErrorMessage } from 'tests/config/errors'; diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index fa13420fc3..c2ed97d50e 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -22,7 +22,7 @@ import type { Source } from '../../../packages/recorder/src/recorderTypes'; import type { CommonFixtures, TestChildProcess } from '../../config/commonFixtures'; import { stripAnsi } from '../../config/utils'; import { expect } from '@playwright/test'; -import { nodePlatform } from '../../../packages/playwright-core/lib/utils/platform'; +import { nodePlatform } from '../../../packages/playwright-core/lib/server/utils/nodePlatform'; export { expect } from '@playwright/test'; type CLITestArgs = { diff --git a/tests/library/modernizr.spec.ts b/tests/library/modernizr.spec.ts index c0a06f3714..0a1b124301 100644 --- a/tests/library/modernizr.spec.ts +++ b/tests/library/modernizr.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { hostPlatform } from '../../packages/playwright-core/src/utils/hostPlatform'; +import { hostPlatform } from '../../packages/playwright-core/src/server/utils/hostPlatform'; import { browserTest as it, expect } from '../config/browserTest'; import fs from 'fs'; import os from 'os'; diff --git a/tests/playwright-test/reporter-blob.spec.ts b/tests/playwright-test/reporter-blob.spec.ts index bf78efc7c8..a8846e69ae 100644 --- a/tests/playwright-test/reporter-blob.spec.ts +++ b/tests/playwright-test/reporter-blob.spec.ts @@ -23,7 +23,7 @@ import { startHtmlReportServer } from '../../packages/playwright/lib/reporters/h import { expect as baseExpect, test as baseTest, stripAnsi } from './playwright-test-fixtures'; import extractZip from '../../packages/playwright-core/bundles/zip/node_modules/extract-zip'; import * as yazl from '../../packages/playwright-core/bundles/zip/node_modules/yazl'; -import { getUserAgent } from '../../packages/playwright-core/lib/utils/userAgent'; +import { getUserAgent } from '../../packages/playwright-core/lib/server/utils/userAgent'; import { Readable } from 'stream'; const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === 'win32' && process.env.TERM_PROGRAM !== 'vscode' && !process.env.WT_SESSION; From ded909c13f354b1dc626cdb9d96bb734c34a481a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 12 Feb 2025 21:13:25 -0800 Subject: [PATCH 05/13] chrome: restore colors enabled/levels logic (#34767) --- .../playwright-core/ThirdPartyNotices.txt | 33 ++++++++++- .../bundles/utils/package-lock.json | 10 ++++ .../bundles/utils/package.json | 1 + .../bundles/utils/src/utilsBundleImpl.ts | 3 + .../playwright-core/src/client/connection.ts | 2 +- .../playwright-core/src/common/platform.ts | 10 ++++ .../src/server/registry/browserFetcher.ts | 3 +- .../src/server/utils/comparators.ts | 3 +- .../src/server/utils/nodePlatform.ts | 3 + packages/playwright-core/src/utils.ts | 3 + .../src/utils/isomorphic/colors.ts | 55 +------------------ .../src/utils/isomorphic/stackTrace.ts | 6 +- packages/playwright-core/src/utilsBundle.ts | 1 + packages/playwright/src/reporters/base.ts | 4 +- packages/playwright/src/util.ts | 3 +- 15 files changed, 75 insertions(+), 65 deletions(-) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index f9d2225d75..420d698fa5 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -11,6 +11,7 @@ This project incorporates components from the projects listed below. The origina - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) - codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) +- colors@1.4.0 (https://github.com/Marak/colors.js) - commander@8.3.0 (https://github.com/tj/commander.js) - concat-map@0.0.1 (https://github.com/substack/node-concat-map) - debug@4.3.4 (https://github.com/debug-js/debug) @@ -354,6 +355,36 @@ THE SOFTWARE. ========================================= END OF codemirror@5.65.18 AND INFORMATION +%% colors@1.4.0 NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Original Library + - Copyright (c) Marak Squires + +Additional Functionality + - Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF colors@1.4.0 AND INFORMATION + %% commander@8.3.0 NOTICES AND INFORMATION BEGIN HERE ========================================= (The MIT License) @@ -1524,6 +1555,6 @@ END OF yazl@2.5.1 AND INFORMATION SUMMARY BEGIN HERE ========================================= -Total Packages: 45 +Total Packages: 46 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index a70731aa0e..bc58353c99 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -8,6 +8,7 @@ "name": "utils-bundle", "version": "0.0.1", "dependencies": { + "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", "diff": "^7.0.0", @@ -162,6 +163,15 @@ "concat-map": "0.0.1" } }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index 76f6a4986a..e7f09cf3a0 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -9,6 +9,7 @@ "generate-license": "node ../../../../utils/generate_third_party_notice.js" }, "dependencies": { + "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", "diff": "^7.0.0", diff --git a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts index 284ca5e7ad..409372e894 100644 --- a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts @@ -16,6 +16,9 @@ /* eslint-disable import/order */ +import colorsLibrary from 'colors/safe'; +export const colors = colorsLibrary; + import debugLibrary from 'debug'; export const debug = debugLibrary; diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts index 124fcc15d5..e37c949f1f 100644 --- a/packages/playwright-core/src/client/connection.ts +++ b/packages/playwright-core/src/client/connection.ts @@ -166,7 +166,7 @@ export class Connection extends EventEmitter { this._callbacks.delete(id); if (error && !result) { const parsedError = parseError(error); - rewriteErrorMessage(parsedError, parsedError.message + formatCallLog(log)); + rewriteErrorMessage(parsedError, parsedError.message + formatCallLog(this.platform, log)); callback.reject(parsedError); } else { const validator = findValidator(callback.type, callback.method, 'Result'); diff --git a/packages/playwright-core/src/common/platform.ts b/packages/playwright-core/src/common/platform.ts index 390dbf80ff..64cef77aab 100644 --- a/packages/playwright-core/src/common/platform.ts +++ b/packages/playwright-core/src/common/platform.ts @@ -18,8 +18,14 @@ import * as crypto from 'crypto'; import * as fs from 'fs'; import * as path from 'path'; +import { webColors, noColors } from '../utils/isomorphic/colors'; + +import type { Colors } from '../utils/isomorphic/colors'; + + export type Platform = { calculateSha1(text: string): Promise; + colors: Colors; createGuid: () => string; fs: () => typeof fs; inspectCustom: symbol | undefined; @@ -37,6 +43,8 @@ export const webPlatform: Platform = { return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join(''); }, + colors: webColors, + createGuid: () => { return Array.from(crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join(''); }, @@ -68,6 +76,8 @@ export const emptyPlatform: Platform = { throw new Error('Not implemented'); }, + colors: noColors, + createGuid: () => { throw new Error('Not implemented'); }, diff --git a/packages/playwright-core/src/server/registry/browserFetcher.ts b/packages/playwright-core/src/server/registry/browserFetcher.ts index fb6afb3f10..6a84f2573a 100644 --- a/packages/playwright-core/src/server/registry/browserFetcher.ts +++ b/packages/playwright-core/src/server/registry/browserFetcher.ts @@ -23,8 +23,7 @@ import * as path from 'path'; import { debugLogger } from '../utils/debugLogger'; import { ManualPromise } from '../../utils/isomorphic/manualPromise'; import { getUserAgent } from '../utils/userAgent'; -import { progress as ProgressBar } from '../../utilsBundle'; -import { colors } from '../../utils/isomorphic/colors'; +import { progress as ProgressBar, colors } from '../../utilsBundle'; import { existsAsync } from '../utils/fileUtils'; import { browserDirectoryToMarkerFilePath } from '.'; diff --git a/packages/playwright-core/src/server/utils/comparators.ts b/packages/playwright-core/src/server/utils/comparators.ts index 19b343cc03..06b6bdc6ff 100644 --- a/packages/playwright-core/src/server/utils/comparators.ts +++ b/packages/playwright-core/src/server/utils/comparators.ts @@ -19,8 +19,7 @@ import { compare } from './image_tools/compare'; // @ts-ignore import pixelmatch from '../../third_party/pixelmatch'; import { jpegjs } from '../../utilsBundle'; -import { colors } from '../../utils/isomorphic/colors'; -import { diff } from '../../utilsBundle'; +import { colors, diff } from '../../utilsBundle'; import { PNG } from '../../utilsBundle'; export type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxDiffPixelRatio?: number, comparator?: string }; diff --git a/packages/playwright-core/src/server/utils/nodePlatform.ts b/packages/playwright-core/src/server/utils/nodePlatform.ts index 1a6f2ddc25..d4b8b5d7ad 100644 --- a/packages/playwright-core/src/server/utils/nodePlatform.ts +++ b/packages/playwright-core/src/server/utils/nodePlatform.ts @@ -19,6 +19,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as util from 'util'; +import { colors } from '../../utilsBundle'; import { Platform } from '../../common/platform'; import { debugLogger } from './debugLogger'; @@ -29,6 +30,8 @@ export const nodePlatform: Platform = { return Promise.resolve(sha1.digest('hex')); }, + colors, + createGuid: () => crypto.randomBytes(16).toString('hex'), fs: () => fs, diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index b4829cb78c..1a0c446c6b 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -44,9 +44,12 @@ export * from './server/utils/fileUtils'; export * from './server/utils/hostPlatform'; export * from './server/utils/httpServer'; export * from './server/utils/network'; +export * from './server/utils/nodePlatform'; export * from './server/utils/processLauncher'; export * from './server/utils/profiler'; export * from './server/utils/socksProxy'; export * from './server/utils/spawnAsync'; export * from './server/utils/userAgent'; export * from './server/utils/wsServer'; + +export { colors } from './utilsBundle'; diff --git a/packages/playwright-core/src/utils/isomorphic/colors.ts b/packages/playwright-core/src/utils/isomorphic/colors.ts index 93ed823628..7be0955ad3 100644 --- a/packages/playwright-core/src/utils/isomorphic/colors.ts +++ b/packages/playwright-core/src/utils/isomorphic/colors.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export const colors = { +export const webColors = { enabled: true, reset: (text: string) => applyStyle(0, 0, text), @@ -36,36 +36,9 @@ export const colors = { white: (text: string) => applyStyle(37, 39, text), gray: (text: string) => applyStyle(90, 39, text), grey: (text: string) => applyStyle(90, 39, text), - - brightRed: (text: string) => applyStyle(91, 39, text), - brightGreen: (text: string) => applyStyle(92, 39, text), - brightYellow: (text: string) => applyStyle(93, 39, text), - brightBlue: (text: string) => applyStyle(94, 39, text), - brightMagenta: (text: string) => applyStyle(95, 39, text), - brightCyan: (text: string) => applyStyle(96, 39, text), - brightWhite: (text: string) => applyStyle(97, 39, text), - - bgBlack: (text: string) => applyStyle(40, 49, text), - bgRed: (text: string) => applyStyle(41, 49, text), - bgGreen: (text: string) => applyStyle(42, 49, text), - bgYellow: (text: string) => applyStyle(43, 49, text), - bgBlue: (text: string) => applyStyle(44, 49, text), - bgMagenta: (text: string) => applyStyle(45, 49, text), - bgCyan: (text: string) => applyStyle(46, 49, text), - bgWhite: (text: string) => applyStyle(47, 49, text), - bgGray: (text: string) => applyStyle(100, 49, text), - bgGrey: (text: string) => applyStyle(100, 49, text), - - bgBrightRed: (text: string) => applyStyle(101, 49, text), - bgBrightGreen: (text: string) => applyStyle(102, 49, text), - bgBrightYellow: (text: string) => applyStyle(103, 49, text), - bgBrightBlue: (text: string) => applyStyle(104, 49, text), - bgBrightMagenta: (text: string) => applyStyle(105, 49, text), - bgBrightCyan: (text: string) => applyStyle(106, 49, text), - bgBrightWhite: (text: string) => applyStyle(107, 49, text), }; -type Colors = typeof colors; +export type Colors = typeof webColors; export const noColors: Colors = { enabled: false, @@ -87,30 +60,6 @@ export const noColors: Colors = { white: t => t, gray: t => t, grey: t => t, - brightRed: t => t, - brightGreen: t => t, - brightYellow: t => t, - brightBlue: t => t, - brightMagenta: t => t, - brightCyan: t => t, - brightWhite: t => t, - bgBlack: t => t, - bgRed: t => t, - bgGreen: t => t, - bgYellow: t => t, - bgBlue: t => t, - bgMagenta: t => t, - bgCyan: t => t, - bgWhite: t => t, - bgGray: t => t, - bgGrey: t => t, - bgBrightRed: t => t, - bgBrightGreen: t => t, - bgBrightYellow: t => t, - bgBrightBlue: t => t, - bgBrightMagenta: t => t, - bgBrightCyan: t => t, - bgBrightWhite: t => t }; diff --git a/packages/playwright-core/src/utils/isomorphic/stackTrace.ts b/packages/playwright-core/src/utils/isomorphic/stackTrace.ts index 7ce3f719a4..26b79c5c27 100644 --- a/packages/playwright-core/src/utils/isomorphic/stackTrace.ts +++ b/packages/playwright-core/src/utils/isomorphic/stackTrace.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { colors } from './colors'; import { findRepeatedSubsequences } from './sequence'; import { parseStackFrame } from './stackUtils'; import type { StackFrame } from '@protocol/channels'; +import type { Platform } from '../../common/platform'; export function parseStackTraceLine(line: string, pathSeparator: string): StackFrame | null { const frame = parseStackFrame(line, pathSeparator); @@ -142,12 +142,12 @@ export function splitErrorMessage(message: string): { name: string, message: str }; } -export function formatCallLog(log: string[] | undefined): string { +export function formatCallLog(platform: Platform, log: string[] | undefined): string { if (!log || !log.some(l => !!l)) return ''; return ` Call log: -${colors.dim(log.join('\n'))} +${platform.colors.dim(log.join('\n'))} `; } diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index a72f18c30f..41cccd1f57 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +export const colors: typeof import('../bundles/utils/node_modules/colors/safe') = require('./utilsBundleImpl').colors; export const debug: typeof import('../bundles/utils/node_modules/@types/debug') = require('./utilsBundleImpl').debug; export const diff: typeof import('../bundles/utils/node_modules/@types/diff') = require('./utilsBundleImpl').diff; export const dotenv: typeof import('../bundles/utils/node_modules/dotenv') = require('./utilsBundleImpl').dotenv; diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 8ba5b23af1..1748cac9b9 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -26,11 +26,11 @@ import { getEastAsianWidth } from '../utilsBundle'; import type { ReporterV2 } from './reporterV2'; import type { FullConfig, FullResult, Location, Suite, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter'; +import type { Colors } from '@isomorphic/colors'; + export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' }; export const kOutputSymbol = Symbol('output'); -type Colors = typeof realColors; - type ErrorDetails = { message: string; location?: Location; diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index a890535fee..b80a3f387d 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -21,6 +21,7 @@ import util from 'util'; import { parseStackTraceLine, sanitizeForFilePath, calculateSha1, formatCallLog, isRegExp, isString, stringifyStackFrames } from 'playwright-core/lib/utils'; import { debug, mime, minimatch } from 'playwright-core/lib/utilsBundle'; +import { nodePlatform } from 'playwright-core/lib/utils'; import type { Location } from './../types/testReporter'; import type { TestInfoErrorImpl } from './common/ipc'; @@ -224,7 +225,7 @@ export function getContainedPath(parentPath: string, subPath: string = ''): stri export const debugTest = debug('pw:test'); -export const callLogText = formatCallLog; +export const callLogText = (log: string[] | undefined) => formatCallLog(nodePlatform, log); const folderToPackageJsonPath = new Map(); From ea67eca5bef5f2258c3f6db19080df35ad0f6771 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 13 Feb 2025 01:05:41 -0800 Subject: [PATCH 06/13] feat(webkit): roll to r2134 (#34754) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 0f0d5f643b..38c5d71834 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -39,7 +39,7 @@ }, { "name": "webkit", - "revision": "2132", + "revision": "2134", "installByDefault": true, "revisionOverrides": { "debian11-x64": "2105", From 5028fb62705b7ab2025c509f541b51a6acc7225e Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 13 Feb 2025 03:09:18 -0800 Subject: [PATCH 07/13] chore(driver): roll driver to recent Node.js LTS version (#34776) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- utils/build/build-playwright-driver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build/build-playwright-driver.sh b/utils/build/build-playwright-driver.sh index c74e3bebf1..6f6082fc8b 100755 --- a/utils/build/build-playwright-driver.sh +++ b/utils/build/build-playwright-driver.sh @@ -4,7 +4,7 @@ set -x trap "cd $(pwd -P)" EXIT SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)" -NODE_VERSION="22.13.1" # autogenerated via ./update-playwright-driver-version.mjs +NODE_VERSION="22.14.0" # autogenerated via ./update-playwright-driver-version.mjs cd "$(dirname "$0")" PACKAGE_VERSION=$(node -p "require('../../package.json').version") From e03402f7a7973145176f42271d299220680e2b37 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 13 Feb 2025 12:11:05 -0800 Subject: [PATCH 08/13] chore(bidi): implement setInputFile(FilePayload) (#34785) --- packages/playwright-core/src/server/bidi/bidiPage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index badd68d1a1..153bb830de 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -520,7 +520,8 @@ export class BidiPage implements PageDelegate { } async setInputFiles(handle: dom.ElementHandle, files: types.FilePayload[]): Promise { - throw new Error('Setting FilePayloads is not supported in Bidi.'); + await handle.evaluateInUtility(([injected, node, files]) => + injected.setInputFiles(node, files), files); } async setInputFilePaths(handle: dom.ElementHandle, paths: string[]): Promise { From 9ecf2f69bafd2217a66a61117ccb64bb09d8cae7 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 13 Feb 2025 12:30:53 -0800 Subject: [PATCH 09/13] chore: move pipe transport utils to server/ (#34787) --- packages/playwright-core/src/cli/driver.ts | 2 +- packages/playwright-core/src/outofprocess.ts | 2 +- packages/playwright-core/src/server/android/android.ts | 4 ++-- .../playwright-core/src/{ => server}/utils/pipeTransport.ts | 0 packages/playwright-core/src/{ => server}/utils/task.ts | 0 packages/playwright-core/src/utils.ts | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename packages/playwright-core/src/{ => server}/utils/pipeTransport.ts (100%) rename packages/playwright-core/src/{ => server}/utils/task.ts (100%) diff --git a/packages/playwright-core/src/cli/driver.ts b/packages/playwright-core/src/cli/driver.ts index 1e16de00bf..104db006cc 100644 --- a/packages/playwright-core/src/cli/driver.ts +++ b/packages/playwright-core/src/cli/driver.ts @@ -19,7 +19,7 @@ import * as fs from 'fs'; import * as playwright from '../..'; -import { PipeTransport } from '../utils/pipeTransport'; +import { PipeTransport } from '../server/utils/pipeTransport'; import { PlaywrightServer } from '../remote/playwrightServer'; import { DispatcherConnection, PlaywrightDispatcher, RootDispatcher, createPlaywright } from '../server'; import { gracefullyProcessExitDoNotHang } from '../server/utils/processLauncher'; diff --git a/packages/playwright-core/src/outofprocess.ts b/packages/playwright-core/src/outofprocess.ts index c24decb900..c2427b818d 100644 --- a/packages/playwright-core/src/outofprocess.ts +++ b/packages/playwright-core/src/outofprocess.ts @@ -18,7 +18,7 @@ import * as childProcess from 'child_process'; import * as path from 'path'; import { Connection } from './client/connection'; -import { PipeTransport } from './utils/pipeTransport'; +import { PipeTransport } from './server/utils/pipeTransport'; import { ManualPromise } from './utils/isomorphic/manualPromise'; import { nodePlatform } from './server/utils/nodePlatform'; diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts index c1516dea76..a4bf8f8ded 100644 --- a/packages/playwright-core/src/server/android/android.ts +++ b/packages/playwright-core/src/server/android/android.ts @@ -20,11 +20,11 @@ import * as os from 'os'; import * as path from 'path'; import { TimeoutSettings } from '../../utils/isomorphic/timeoutSettings'; -import { PipeTransport } from '../../utils/pipeTransport'; +import { PipeTransport } from '../utils/pipeTransport'; import { createGuid } from '../utils/crypto'; import { isUnderTest } from '../../utils/isomorphic/debug'; import { getPackageManagerExecCommand } from '../utils/env'; -import { makeWaitForNextTask } from '../../utils/task'; +import { makeWaitForNextTask } from '../utils/task'; import { RecentLogsCollector } from '../utils/debugLogger'; import { debug } from '../../utilsBundle'; import { wsReceiver, wsSender } from '../../utilsBundle'; diff --git a/packages/playwright-core/src/utils/pipeTransport.ts b/packages/playwright-core/src/server/utils/pipeTransport.ts similarity index 100% rename from packages/playwright-core/src/utils/pipeTransport.ts rename to packages/playwright-core/src/server/utils/pipeTransport.ts diff --git a/packages/playwright-core/src/utils/task.ts b/packages/playwright-core/src/server/utils/task.ts similarity index 100% rename from packages/playwright-core/src/utils/task.ts rename to packages/playwright-core/src/server/utils/task.ts diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index 1a0c446c6b..a61f84801c 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -29,7 +29,6 @@ export * from './utils/isomorphic/urlMatch'; export * from './utils/isomorphic/headers'; export * from './utils/isomorphic/semaphore'; export * from './utils/isomorphic/stackTrace'; -export * from './utils/task'; export * from './utils/zipFile'; export * from './utils/zones'; @@ -49,6 +48,7 @@ export * from './server/utils/processLauncher'; export * from './server/utils/profiler'; export * from './server/utils/socksProxy'; export * from './server/utils/spawnAsync'; +export * from './server/utils/task'; export * from './server/utils/userAgent'; export * from './server/utils/wsServer'; From 90ec8383189d4d122e68c51ef7f43528ccdfa754 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 13 Feb 2025 13:06:03 -0800 Subject: [PATCH 10/13] chore: move zones into platform (#34786) --- .../src/client/browserContext.ts | 2 +- .../src/client/channelOwner.ts | 5 +-- .../playwright-core/src/client/connection.ts | 3 +- .../playwright-core/src/client/network.ts | 11 +++-- packages/playwright-core/src/client/page.ts | 2 +- packages/playwright-core/src/client/waiter.ts | 5 +-- .../playwright-core/src/common/platform.ts | 20 +++++++++- .../src/server/utils/nodePlatform.ts | 40 ++++++++++++++++++- .../src/{ => server}/utils/zones.ts | 33 ++++----------- packages/playwright-core/src/utils.ts | 2 +- packages/playwright/src/common/testType.ts | 4 +- packages/playwright/src/index.ts | 4 +- packages/playwright/src/matchers/expect.ts | 4 +- packages/playwright/src/worker/testInfo.ts | 4 +- 14 files changed, 85 insertions(+), 54 deletions(-) rename packages/playwright-core/src/{ => server}/utils/zones.ts (63%) diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index 02aa857366..d03cfcdeca 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -338,7 +338,7 @@ export class BrowserContext extends ChannelOwner } async route(url: URLMatch, handler: network.RouteHandlerCallback, options: { times?: number } = {}): Promise { - this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times)); + this._routes.unshift(new network.RouteHandler(this._platform, this._options.baseURL, url, handler, options.times)); await this._updateInterceptionPatterns(); } diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 40bf226c65..92deaecabd 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -18,7 +18,6 @@ import { EventEmitter } from './eventEmitter'; import { ValidationError, maybeFindValidator } from '../protocol/validator'; import { isUnderTest } from '../utils/isomorphic/debug'; import { captureLibraryStackTrace, stringifyStackFrames } from '../utils/isomorphic/stackTrace'; -import { zones } from '../utils/zones'; import type { ClientInstrumentation } from './clientInstrumentation'; import type { Connection } from './connection'; @@ -176,7 +175,7 @@ export abstract class ChannelOwner(func: (apiZone: ApiZone) => Promise, isInternal?: boolean): Promise { const logger = this._logger; - const existingApiZone = zones.zoneData('apiZone'); + const existingApiZone = this._platform.zones.current().data(); if (existingApiZone) return await func(existingApiZone); @@ -186,7 +185,7 @@ export abstract class ChannelOwner await func(apiZone)); + const result = await this._platform.zones.current().push(apiZone).run(async () => await func(apiZone)); if (!isInternal) { logApiCall(this._platform, logger, `<= ${apiZone.apiName} succeeded`); this._instrumentation.onApiCallEnd(apiZone); diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts index e37c949f1f..963b13a77f 100644 --- a/packages/playwright-core/src/client/connection.ts +++ b/packages/playwright-core/src/client/connection.ts @@ -43,7 +43,6 @@ import { Worker } from './worker'; import { WritableStream } from './writableStream'; import { ValidationError, findValidator } from '../protocol/validator'; import { formatCallLog, rewriteErrorMessage } from '../utils/isomorphic/stackTrace'; -import { zones } from '../utils/zones'; import type { ClientInstrumentation } from './clientInstrumentation'; import type { HeadersArray } from './types'; @@ -148,7 +147,7 @@ export class Connection extends EventEmitter { this._localUtils?.addStackToTracingNoReply({ callData: { stack: frames, id } }).catch(() => {}); // We need to exit zones before calling into the server, otherwise // when we receive events from the server, we would be in an API zone. - zones.empty().run(() => this.onmessage({ ...message, metadata })); + this.platform.zones.empty.run(() => this.onmessage({ ...message, metadata })); return await new Promise((resolve, reject) => this._callbacks.set(id, { resolve, reject, apiName, type, method })); } diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index a2c64c08b1..3770ca1320 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -30,7 +30,6 @@ import { LongStandingScope, ManualPromise } from '../utils/isomorphic/manualProm import { MultiMap } from '../utils/isomorphic/multimap'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace'; -import { zones } from '../utils/zones'; import { mime } from '../utilsBundle'; import type { BrowserContext } from './browserContext'; @@ -40,8 +39,8 @@ import type { Serializable } from '../../types/structs'; import type * as api from '../../types/types'; import type { HeadersArray } from '../common/types'; import type { URLMatch } from '../utils/isomorphic/urlMatch'; -import type { Zone } from '../utils/zones'; import type * as channels from '@protocol/channels'; +import type { Platform, Zone } from '../common/platform'; export type NetworkCookie = { name: string, @@ -821,14 +820,14 @@ export class RouteHandler { readonly handler: RouteHandlerCallback; private _ignoreException: boolean = false; private _activeInvocations: Set<{ complete: Promise, route: Route }> = new Set(); - private _svedZone: Zone; + private _savedZone: Zone; - constructor(baseURL: string | undefined, url: URLMatch, handler: RouteHandlerCallback, times: number = Number.MAX_SAFE_INTEGER) { + constructor(platform: Platform, baseURL: string | undefined, url: URLMatch, handler: RouteHandlerCallback, times: number = Number.MAX_SAFE_INTEGER) { this._baseURL = baseURL; this._times = times; this.url = url; this.handler = handler; - this._svedZone = zones.current().without('apiZone'); + this._savedZone = platform.zones.current().pop(); } static prepareInterceptionPatterns(handlers: RouteHandler[]) { @@ -852,7 +851,7 @@ export class RouteHandler { } public async handle(route: Route): Promise { - return await this._svedZone.run(async () => this._handleImpl(route)); + return await this._savedZone.run(async () => this._handleImpl(route)); } private async _handleImpl(route: Route): Promise { diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index b954cca502..062217937c 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -520,7 +520,7 @@ export class Page extends ChannelOwner implements api.Page } async route(url: URLMatch, handler: RouteHandlerCallback, options: { times?: number } = {}): Promise { - this._routes.unshift(new RouteHandler(this._browserContext._options.baseURL, url, handler, options.times)); + this._routes.unshift(new RouteHandler(this._platform, this._browserContext._options.baseURL, url, handler, options.times)); await this._updateInterceptionPatterns(); } diff --git a/packages/playwright-core/src/client/waiter.ts b/packages/playwright-core/src/client/waiter.ts index e17f93d940..7d07d2128e 100644 --- a/packages/playwright-core/src/client/waiter.ts +++ b/packages/playwright-core/src/client/waiter.ts @@ -16,12 +16,11 @@ import { TimeoutError } from './errors'; import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace'; -import { zones } from '../utils/zones'; import type { ChannelOwner } from './channelOwner'; -import type { Zone } from '../utils/zones'; import type * as channels from '@protocol/channels'; import type { EventEmitter } from 'events'; +import type { Zone } from '../common/platform'; export class Waiter { private _dispose: (() => void)[]; @@ -36,7 +35,7 @@ export class Waiter { constructor(channelOwner: ChannelOwner, event: string) { this._waitId = channelOwner._platform.createGuid(); this._channelOwner = channelOwner; - this._savedZone = zones.current().without('apiZone'); + this._savedZone = channelOwner._platform.zones.current().pop(); this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: 'before', event } }).catch(() => {}); this._dispose = [ diff --git a/packages/playwright-core/src/common/platform.ts b/packages/playwright-core/src/common/platform.ts index 64cef77aab..bb73ec6d31 100644 --- a/packages/playwright-core/src/common/platform.ts +++ b/packages/playwright-core/src/common/platform.ts @@ -22,6 +22,19 @@ import { webColors, noColors } from '../utils/isomorphic/colors'; import type { Colors } from '../utils/isomorphic/colors'; +export type Zone = { + push(data: unknown): Zone; + pop(): Zone; + run(func: () => R): R; + data(): T | undefined; +}; + +const noopZone: Zone = { + push: () => noopZone, + pop: () => noopZone, + run: func => func(), + data: () => undefined, +}; export type Platform = { calculateSha1(text: string): Promise; @@ -34,6 +47,7 @@ export type Platform = { path: () => typeof path; pathSeparator: string; ws?: (url: string) => WebSocket; + zones: { empty: Zone, current: () => Zone; }; }; export const webPlatform: Platform = { @@ -69,6 +83,8 @@ export const webPlatform: Platform = { pathSeparator: '/', ws: (url: string) => new WebSocket(url), + + zones: { empty: noopZone, current: () => noopZone }, }; export const emptyPlatform: Platform = { @@ -98,5 +114,7 @@ export const emptyPlatform: Platform = { throw new Error('Function not implemented.'); }, - pathSeparator: '/' + pathSeparator: '/', + + zones: { empty: noopZone, current: () => noopZone }, }; diff --git a/packages/playwright-core/src/server/utils/nodePlatform.ts b/packages/playwright-core/src/server/utils/nodePlatform.ts index d4b8b5d7ad..49f6b23ffe 100644 --- a/packages/playwright-core/src/server/utils/nodePlatform.ts +++ b/packages/playwright-core/src/server/utils/nodePlatform.ts @@ -20,8 +20,39 @@ import * as path from 'path'; import * as util from 'util'; import { colors } from '../../utilsBundle'; -import { Platform } from '../../common/platform'; import { debugLogger } from './debugLogger'; +import { currentZone, emptyZone } from './zones'; + +import type { Platform, Zone } from '../../common/platform'; +import type { Zone as ZoneImpl } from './zones'; + +class NodeZone implements Zone { + private _zone: ZoneImpl; + + constructor(zone: ZoneImpl) { + this._zone = zone; + } + + push(data: T) { + return new NodeZone(this._zone.with('apiZone', data)); + } + + pop() { + return new NodeZone(this._zone.without('apiZone')); + } + + run(func: () => R): R { + return this._zone.run(func); + } + + runIgnoreCurrent(func: () => R): R { + return emptyZone.run(func); + } + + data(): T | undefined { + return this._zone.data('apiZone'); + } +} export const nodePlatform: Platform = { calculateSha1: (text: string) => { @@ -48,5 +79,10 @@ export const nodePlatform: Platform = { path: () => path, - pathSeparator: path.sep + pathSeparator: path.sep, + + zones: { + current: () => new NodeZone(currentZone()), + empty: new NodeZone(emptyZone), + } }; diff --git a/packages/playwright-core/src/utils/zones.ts b/packages/playwright-core/src/server/utils/zones.ts similarity index 63% rename from packages/playwright-core/src/utils/zones.ts rename to packages/playwright-core/src/server/utils/zones.ts index 32664c3898..b5860167b0 100644 --- a/packages/playwright-core/src/utils/zones.ts +++ b/packages/playwright-core/src/server/utils/zones.ts @@ -18,36 +18,13 @@ import { AsyncLocalStorage } from 'async_hooks'; export type ZoneType = 'apiZone' | 'stepZone'; -class ZoneManager { - private readonly _asyncLocalStorage = new AsyncLocalStorage(); - private readonly _emptyZone = Zone.createEmpty(this._asyncLocalStorage); - - run(type: ZoneType, data: T, func: () => R): R { - return this.current().with(type, data).run(func); - } - - zoneData(type: ZoneType): T | undefined { - return this.current().data(type); - } - - current(): Zone { - return this._asyncLocalStorage.getStore() ?? this._emptyZone; - } - - empty(): Zone { - return this._emptyZone; - } -} +const asyncLocalStorage = new AsyncLocalStorage(); export class Zone { private readonly _asyncLocalStorage: AsyncLocalStorage; private readonly _data: ReadonlyMap; - static createEmpty(asyncLocalStorage: AsyncLocalStorage) { - return new Zone(asyncLocalStorage, new Map()); - } - - private constructor(asyncLocalStorage: AsyncLocalStorage, store: Map) { + constructor(asyncLocalStorage: AsyncLocalStorage, store: Map) { this._asyncLocalStorage = asyncLocalStorage; this._data = store; } @@ -71,4 +48,8 @@ export class Zone { } } -export const zones = new ZoneManager(); +export const emptyZone = new Zone(asyncLocalStorage, new Map()); + +export function currentZone(): Zone { + return asyncLocalStorage.getStore() ?? emptyZone; +} diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index a61f84801c..839aa390a8 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -30,7 +30,6 @@ export * from './utils/isomorphic/headers'; export * from './utils/isomorphic/semaphore'; export * from './utils/isomorphic/stackTrace'; export * from './utils/zipFile'; -export * from './utils/zones'; export * from './server/utils/ascii'; export * from './server/utils/comparators'; @@ -51,5 +50,6 @@ export * from './server/utils/spawnAsync'; export * from './server/utils/task'; export * from './server/utils/userAgent'; export * from './server/utils/wsServer'; +export * from './server/utils/zones'; export { colors } from './utilsBundle'; diff --git a/packages/playwright/src/common/testType.ts b/packages/playwright/src/common/testType.ts index 7395e38217..d9c828cc62 100644 --- a/packages/playwright/src/common/testType.ts +++ b/packages/playwright/src/common/testType.ts @@ -15,7 +15,7 @@ */ import { errors } from 'playwright-core'; -import { getPackageManagerExecCommand, monotonicTime, raceAgainstDeadline, zones } from 'playwright-core/lib/utils'; +import { getPackageManagerExecCommand, monotonicTime, raceAgainstDeadline, currentZone } from 'playwright-core/lib/utils'; import { currentTestInfo, currentlyLoadingFileSuite, setCurrentlyLoadingFileSuite } from './globals'; import { Suite, TestCase } from './test'; @@ -266,7 +266,7 @@ export class TestTypeImpl { if (!testInfo) throw new Error(`test.step() can only be called from a test`); const step = testInfo._addStep({ category: 'test.step', title, location: options.location, box: options.box }); - return await zones.run('stepZone', step, async () => { + return await currentZone().with('stepZone', step).run(async () => { try { let result: Awaited>> | undefined = undefined; result = await raceAgainstDeadline(async () => { diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index a8d0cc0387..9d6089614c 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -18,7 +18,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as playwrightLibrary from 'playwright-core'; -import { addInternalStackPrefix, asLocator, createGuid, debugMode, isString, jsonStringifyForceASCII, zones } from 'playwright-core/lib/utils'; +import { addInternalStackPrefix, asLocator, createGuid, currentZone, debugMode, isString, jsonStringifyForceASCII } from 'playwright-core/lib/utils'; import { currentTestInfo } from './common/globals'; import { rootTestType } from './common/testType'; @@ -260,7 +260,7 @@ const playwrightFixtures: Fixtures = ({ // Some special calls do not get into steps. if (!testInfo || data.apiName.includes('setTestIdAttribute') || data.apiName === 'tracing.groupEnd') return; - const zone = zones.zoneData('stepZone'); + const zone = currentZone().data('stepZone'); if (zone && zone.category === 'expect') { // Display the internal locator._expect call under the name of the enclosing expect call, // and connect it to the existing expect step. diff --git a/packages/playwright/src/matchers/expect.ts b/packages/playwright/src/matchers/expect.ts index 707e5457e1..58eb9be9fc 100644 --- a/packages/playwright/src/matchers/expect.ts +++ b/packages/playwright/src/matchers/expect.ts @@ -17,9 +17,9 @@ import { captureRawStack, createGuid, + currentZone, isString, pollAgainstDeadline } from 'playwright-core/lib/utils'; -import { zones } from 'playwright-core/lib/utils'; import { ExpectError, isJestError } from './matcherHint'; import { @@ -380,7 +380,7 @@ class ExpectMetaInfoProxyHandler implements ProxyHandler { try { setMatcherCallContext({ expectInfo: this._info, testInfo, step: step.info }); const callback = () => matcher.call(target, ...args); - const result = zones.run('stepZone', step, callback); + const result = currentZone().with('stepZone', step).run(callback); if (result instanceof Promise) return result.then(finalizer).catch(reportStepError); finalizer(); diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index 5e964af5e0..cbb26b6c2f 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -17,7 +17,7 @@ import * as fs from 'fs'; import * as path from 'path'; -import { captureRawStack, monotonicTime, sanitizeForFilePath, stringifyStackFrames, zones } from 'playwright-core/lib/utils'; +import { captureRawStack, monotonicTime, sanitizeForFilePath, stringifyStackFrames, currentZone } from 'playwright-core/lib/utils'; import { TimeoutManager, TimeoutManagerError, kMaxDeadline } from './timeoutManager'; import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, trimLongString, windowsFilesystemFriendlyLength } from '../util'; @@ -245,7 +245,7 @@ export class TestInfoImpl implements TestInfo { } private _parentStep() { - return zones.zoneData('stepZone') + return currentZone().data('stepZone') ?? this._findLastStageStep(this._steps); // If no parent step on stack, assume the current stage as parent. } From 163aacf4b68a9155a6a9fe2474d4bf2a9c130b10 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 13 Feb 2025 16:15:11 -0800 Subject: [PATCH 11/13] chore: allow client operation w/o local utils (#34790) --- packages/playwright-core/src/client/DEPS.list | 3 +- .../playwright-core/src/client/android.ts | 4 +- .../playwright-core/src/client/artifact.ts | 2 +- .../playwright-core/src/client/browser.ts | 2 +- .../src/client/browserContext.ts | 12 +- .../playwright-core/src/client/browserType.ts | 4 +- .../playwright-core/src/client/connection.ts | 4 +- .../src/client/elementHandle.ts | 6 +- packages/playwright-core/src/client/fetch.ts | 2 +- .../src/{common => client}/fileUtils.ts | 9 +- .../playwright-core/src/client/localUtils.ts | 122 +---- .../playwright-core/src/client/network.ts | 4 +- packages/playwright-core/src/client/page.ts | 7 +- .../playwright-core/src/client/tracing.ts | 16 +- .../playwright-core/src/client/webSocket.ts | 116 +++++ packages/playwright-core/src/common/DEPS.list | 3 - .../playwright-core/src/common/platform.ts | 19 +- .../playwright-core/src/common/progress.ts | 23 - .../playwright-core/src/protocol/DEPS.list | 3 +- .../src/protocol/validatorPrimitives.ts | 2 +- .../dispatchers/localUtilsDispatcher.ts | 11 +- .../src/server/fileUploadUtils.ts | 4 +- .../src/{common => server}/harBackend.ts | 17 +- .../src/{common => server}/localUtils.ts | 28 +- .../playwright-core/src/server/progress.ts | 8 +- .../src/server/utils/nodePlatform.ts | 6 +- .../src/{ => server}/utils/zipFile.ts | 4 +- packages/playwright-core/src/utils.ts | 2 +- .../src/utils/isomorphic/mimeType.ts | 427 +++++++++++++++++- tests/config/utils.ts | 2 +- 30 files changed, 646 insertions(+), 226 deletions(-) rename packages/playwright-core/src/{common => client}/fileUtils.ts (75%) create mode 100644 packages/playwright-core/src/client/webSocket.ts delete mode 100644 packages/playwright-core/src/common/progress.ts rename packages/playwright-core/src/{common => server}/harBackend.ts (92%) rename packages/playwright-core/src/{common => server}/localUtils.ts (84%) rename packages/playwright-core/src/{ => server}/utils/zipFile.ts (95%) diff --git a/packages/playwright-core/src/client/DEPS.list b/packages/playwright-core/src/client/DEPS.list index 4be2917927..e886cdbe63 100644 --- a/packages/playwright-core/src/client/DEPS.list +++ b/packages/playwright-core/src/client/DEPS.list @@ -1,5 +1,4 @@ [*] ../common/ ../protocol/ -../utils/** -../utilsBundle.ts +../utils/isomorphic diff --git a/packages/playwright-core/src/client/android.ts b/packages/playwright-core/src/client/android.ts index f0ca11848f..3aedc5c4ac 100644 --- a/packages/playwright-core/src/client/android.ts +++ b/packages/playwright-core/src/client/android.ts @@ -25,6 +25,7 @@ import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; import { monotonicTime } from '../utils/isomorphic/time'; import { raceAgainstDeadline } from '../utils/isomorphic/timeoutRunner'; +import { connectOverWebSocket } from './webSocket'; import type { Page } from './page'; import type * as types from './types'; @@ -69,9 +70,8 @@ export class Android extends ChannelOwner implements ap return await this._wrapApiCall(async () => { const deadline = options.timeout ? monotonicTime() + options.timeout : 0; const headers = { 'x-playwright-browser': 'android', ...options.headers }; - const localUtils = this._connection.localUtils(); const connectParams: channels.LocalUtilsConnectParams = { wsEndpoint, headers, slowMo: options.slowMo, timeout: options.timeout }; - const connection = await localUtils.connect(connectParams); + const connection = await connectOverWebSocket(this._connection, connectParams); let device: AndroidDevice; connection.on('close', () => { diff --git a/packages/playwright-core/src/client/artifact.ts b/packages/playwright-core/src/client/artifact.ts index 815c7a358b..7c6fd947cf 100644 --- a/packages/playwright-core/src/client/artifact.ts +++ b/packages/playwright-core/src/client/artifact.ts @@ -16,7 +16,7 @@ import { ChannelOwner } from './channelOwner'; import { Stream } from './stream'; -import { mkdirIfNeeded } from '../common/fileUtils'; +import { mkdirIfNeeded } from './fileUtils'; import type * as channels from '@protocol/channels'; import type { Readable } from 'stream'; diff --git a/packages/playwright-core/src/client/browser.ts b/packages/playwright-core/src/client/browser.ts index 88140621fe..a12bf108a8 100644 --- a/packages/playwright-core/src/client/browser.ts +++ b/packages/playwright-core/src/client/browser.ts @@ -20,7 +20,7 @@ import { CDPSession } from './cdpSession'; import { ChannelOwner } from './channelOwner'; import { isTargetClosedError } from './errors'; import { Events } from './events'; -import { mkdirIfNeeded } from '../common/fileUtils'; +import { mkdirIfNeeded } from './fileUtils'; import type { BrowserType } from './browserType'; import type { Page } from './page'; diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index d03cfcdeca..21f5a200b7 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -35,7 +35,7 @@ import { Waiter } from './waiter'; import { WebError } from './webError'; import { Worker } from './worker'; import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; -import { mkdirIfNeeded } from '../common/fileUtils'; +import { mkdirIfNeeded } from './fileUtils'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { urlMatchesEqual } from '../utils/isomorphic/urlMatch'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; @@ -361,11 +361,14 @@ export class BrowserContext extends ChannelOwner } async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback', update?: boolean, updateContent?: 'attach' | 'embed', updateMode?: 'minimal' | 'full' } = {}): Promise { + const localUtils = this._connection.localUtils(); + if (!localUtils) + throw new Error('Route from har is not supported in thin clients'); if (options.update) { await this._recordIntoHAR(har, null, options); return; } - const harRouter = await HarRouter.create(this._connection.localUtils(), har, options.notFound || 'abort', { urlMatch: options.url }); + const harRouter = await HarRouter.create(localUtils, har, options.notFound || 'abort', { urlMatch: options.url }); this._harRouters.push(harRouter); await harRouter.addContextRoute(this); } @@ -484,8 +487,11 @@ export class BrowserContext extends ChannelOwner const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip'); const needCompressed = harParams.path.endsWith('.zip'); if (isCompressed && !needCompressed) { + const localUtils = this._connection.localUtils(); + if (!localUtils) + throw new Error('Uncompressed har is not supported in thin clients'); await artifact.saveAs(harParams.path + '.tmp'); - await this._connection.localUtils().harUnzip({ zipFile: harParams.path + '.tmp', harFile: harParams.path }); + await localUtils.harUnzip({ zipFile: harParams.path + '.tmp', harFile: harParams.path }); } else { await artifact.saveAs(harParams.path); } diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index 06bae0419f..39a9a3f1cc 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -25,6 +25,7 @@ import { assert } from '../utils/isomorphic/debug'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { monotonicTime } from '../utils/isomorphic/time'; import { raceAgainstDeadline } from '../utils/isomorphic/timeoutRunner'; +import { connectOverWebSocket } from './webSocket'; import type { Playwright } from './playwright'; import type { ConnectOptions, LaunchOptions, LaunchPersistentContextOptions, LaunchServerOptions, Logger } from './types'; @@ -124,7 +125,6 @@ export class BrowserType extends ChannelOwner imple return await this._wrapApiCall(async () => { const deadline = params.timeout ? monotonicTime() + params.timeout : 0; const headers = { 'x-playwright-browser': this.name(), ...params.headers }; - const localUtils = this._connection.localUtils(); const connectParams: channels.LocalUtilsConnectParams = { wsEndpoint: params.wsEndpoint, headers, @@ -134,7 +134,7 @@ export class BrowserType extends ChannelOwner imple }; if ((params as any).__testHookRedirectPortForwarding) connectParams.socksProxyRedirectPortForTest = (params as any).__testHookRedirectPortForwarding; - const connection = await localUtils.connect(connectParams); + const connection = await connectOverWebSocket(this._connection, connectParams); let browser: Browser; connection.on('close', () => { // Emulate all pages, contexts and the browser closing upon disconnect. diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts index 963b13a77f..929acff25f 100644 --- a/packages/playwright-core/src/client/connection.ts +++ b/packages/playwright-core/src/client/connection.ts @@ -108,8 +108,8 @@ export class Connection extends EventEmitter { return this._rawBuffers; } - localUtils(): LocalUtils { - return this._localUtils!; + localUtils(): LocalUtils | undefined { + return this._localUtils; } async initializePlaywright(): Promise { diff --git a/packages/playwright-core/src/client/elementHandle.ts b/packages/playwright-core/src/client/elementHandle.ts index 206fc33084..b1ef721ce3 100644 --- a/packages/playwright-core/src/client/elementHandle.ts +++ b/packages/playwright-core/src/client/elementHandle.ts @@ -20,10 +20,10 @@ import { promisify } from 'util'; import { Frame } from './frame'; import { JSHandle, parseResult, serializeArgument } from './jsHandle'; import { assert } from '../utils/isomorphic/debug'; -import { fileUploadSizeLimit, mkdirIfNeeded } from '../common/fileUtils'; +import { fileUploadSizeLimit, mkdirIfNeeded } from './fileUtils'; import { isString } from '../utils/isomorphic/rtti'; -import { mime } from '../utilsBundle'; import { WritableStream } from './writableStream'; +import { getMimeTypeForPath } from '../utils/isomorphic/mimeType'; import type { BrowserContext } from './browserContext'; import type { ChannelOwner } from './channelOwner'; @@ -327,7 +327,7 @@ export async function convertInputFiles(platform: Platform, files: string | File export function determineScreenshotType(options: { path?: string, type?: 'png' | 'jpeg' }): 'png' | 'jpeg' | undefined { if (options.path) { - const mimeType = mime.getType(options.path); + const mimeType = getMimeTypeForPath(options.path); if (mimeType === 'image/png') return 'png'; else if (mimeType === 'image/jpeg') diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index 8e02bc34a2..41070b8665 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -20,7 +20,7 @@ import { TargetClosedError, isTargetClosedError } from './errors'; import { RawHeaders } from './network'; import { Tracing } from './tracing'; import { assert } from '../utils/isomorphic/debug'; -import { mkdirIfNeeded } from '../common/fileUtils'; +import { mkdirIfNeeded } from './fileUtils'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { isString } from '../utils/isomorphic/rtti'; diff --git a/packages/playwright-core/src/common/fileUtils.ts b/packages/playwright-core/src/client/fileUtils.ts similarity index 75% rename from packages/playwright-core/src/common/fileUtils.ts rename to packages/playwright-core/src/client/fileUtils.ts index 261b72d84a..0d21b195c0 100644 --- a/packages/playwright-core/src/common/fileUtils.ts +++ b/packages/playwright-core/src/client/fileUtils.ts @@ -14,17 +14,12 @@ * limitations under the License. */ -import type { Platform } from './platform'; +import type { Platform } from '../common/platform'; +// Keep in sync with the server. export const fileUploadSizeLimit = 50 * 1024 * 1024; export async function mkdirIfNeeded(platform: Platform, filePath: string) { // This will harmlessly throw on windows if the dirname is the root directory. await platform.fs().promises.mkdir(platform.path().dirname(filePath), { recursive: true }).catch(() => {}); } - -export async function removeFolders(platform: Platform, dirs: string[]): Promise { - return await Promise.all(dirs.map((dir: string) => - platform.fs().promises.rm(dir, { recursive: true, force: true, maxRetries: 10 }).catch(e => e) - )); -} diff --git a/packages/playwright-core/src/client/localUtils.ts b/packages/playwright-core/src/client/localUtils.ts index ad66de6814..5ba982251f 100644 --- a/packages/playwright-core/src/client/localUtils.ts +++ b/packages/playwright-core/src/client/localUtils.ts @@ -15,12 +15,8 @@ */ import { ChannelOwner } from './channelOwner'; -import { Connection } from './connection'; -import * as localUtils from '../common/localUtils'; -import type { HeadersArray, Size } from './types'; -import type { HarBackend } from '../common/harBackend'; -import type { Platform } from '../common/platform'; +import type { Size } from './types'; import type * as channels from '@protocol/channels'; type DeviceDescriptor = { @@ -35,8 +31,6 @@ type Devices = { [name: string]: DeviceDescriptor }; export class LocalUtils extends ChannelOwner { readonly devices: Devices; - private _harBackends = new Map(); - private _stackSessions = new Map(); constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.LocalUtilsInitializer) { super(parent, type, guid, initializer); @@ -47,132 +41,34 @@ export class LocalUtils extends ChannelOwner { } async zip(params: channels.LocalUtilsZipParams): Promise { - return await localUtils.zip(this._platform, this._stackSessions, params); + return await this._channel.zip(params); } async harOpen(params: channels.LocalUtilsHarOpenParams): Promise { - return await localUtils.harOpen(this._platform, this._harBackends, params); + return await this._channel.harOpen(params); } async harLookup(params: channels.LocalUtilsHarLookupParams): Promise { - return await localUtils.harLookup(this._harBackends, params); + return await this._channel.harLookup(params); } async harClose(params: channels.LocalUtilsHarCloseParams): Promise { - return await localUtils.harClose(this._harBackends, params); + return await this._channel.harClose(params); } async harUnzip(params: channels.LocalUtilsHarUnzipParams): Promise { - return await localUtils.harUnzip(params); + return await this._channel.harUnzip(params); } async tracingStarted(params: channels.LocalUtilsTracingStartedParams): Promise { - return await localUtils.tracingStarted(this._stackSessions, params); + return await this._channel.tracingStarted(params); } async traceDiscarded(params: channels.LocalUtilsTraceDiscardedParams): Promise { - return await localUtils.traceDiscarded(this._platform, this._stackSessions, params); + return await this._channel.traceDiscarded(params); } async addStackToTracingNoReply(params: channels.LocalUtilsAddStackToTracingNoReplyParams): Promise { - return await localUtils.addStackToTracingNoReply(this._stackSessions, params); - } - - async connect(params: channels.LocalUtilsConnectParams): Promise { - const transport = this._platform.ws ? new WebSocketTransport(this._platform) : new JsonPipeTransport(this); - const connectHeaders = await transport.connect(params); - const connection = new Connection(this, this._platform, this._instrumentation, connectHeaders); - connection.markAsRemote(); - connection.on('close', () => transport.close()); - - let closeError: string | undefined; - const onTransportClosed = (reason?: string) => { - connection.close(reason || closeError); - }; - transport.onClose(reason => onTransportClosed(reason)); - connection.onmessage = message => transport.send(message).catch(() => onTransportClosed()); - transport.onMessage(message => { - try { - connection!.dispatch(message); - } catch (e) { - closeError = String(e); - transport.close(); - } - }); - return connection; - } -} -interface Transport { - connect(params: channels.LocalUtilsConnectParams): Promise; - send(message: any): Promise; - onMessage(callback: (message: object) => void): void; - onClose(callback: (reason?: string) => void): void; - close(): Promise; -} - -class JsonPipeTransport implements Transport { - private _pipe: channels.JsonPipeChannel | undefined; - private _owner: ChannelOwner; - - constructor(owner: ChannelOwner) { - this._owner = owner; - } - - async connect(params: channels.LocalUtilsConnectParams) { - const { pipe, headers: connectHeaders } = await this._owner._wrapApiCall(async () => { - return await this._owner._channel.connect(params); - }, /* isInternal */ true); - this._pipe = pipe; - return connectHeaders; - } - - async send(message: object) { - this._owner._wrapApiCall(async () => { - await this._pipe!.send({ message }); - }, /* isInternal */ true); - } - - onMessage(callback: (message: object) => void) { - this._pipe!.on('message', ({ message }) => callback(message)); - } - - onClose(callback: (reason?: string) => void) { - this._pipe!.on('closed', ({ reason }) => callback(reason)); - } - - async close() { - await this._owner._wrapApiCall(async () => { - await this._pipe!.close().catch(() => {}); - }, /* isInternal */ true); - } -} - -class WebSocketTransport implements Transport { - private _platform: Platform; - private _ws: WebSocket | undefined; - - constructor(platform: Platform) { - this._platform = platform; - } - - async connect(params: channels.LocalUtilsConnectParams) { - this._ws = this._platform.ws!(params.wsEndpoint); - return []; - } - - async send(message: object) { - this._ws!.send(JSON.stringify(message)); - } - - onMessage(callback: (message: object) => void) { - this._ws!.addEventListener('message', event => callback(JSON.parse(event.data))); - } - - onClose(callback: (reason?: string) => void) { - this._ws!.addEventListener('close', () => callback()); - } - - async close() { - this._ws!.close(); + return await this._channel.addStackToTracingNoReply(params); } } diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index 3770ca1320..ff992e7ae7 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -30,7 +30,7 @@ import { LongStandingScope, ManualPromise } from '../utils/isomorphic/manualProm import { MultiMap } from '../utils/isomorphic/multimap'; import { isRegExp, isString } from '../utils/isomorphic/rtti'; import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace'; -import { mime } from '../utilsBundle'; +import { getMimeTypeForPath } from '../utils/isomorphic/mimeType'; import type { BrowserContext } from './browserContext'; import type { Page } from './page'; @@ -413,7 +413,7 @@ export class Route extends ChannelOwner implements api.Ro else if (options.json) headers['content-type'] = 'application/json'; else if (options.path) - headers['content-type'] = mime.getType(options.path) || 'application/octet-stream'; + headers['content-type'] = getMimeTypeForPath(options.path) || 'application/octet-stream'; if (length && !('content-length' in headers)) headers['content-length'] = String(length); diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index 062217937c..43c43ee50c 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -35,7 +35,7 @@ import { Waiter } from './waiter'; import { Worker } from './worker'; import { TimeoutSettings } from '../utils/isomorphic/timeoutSettings'; import { assert } from '../utils/isomorphic/debug'; -import { mkdirIfNeeded } from '../common/fileUtils'; +import { mkdirIfNeeded } from './fileUtils'; import { headersObjectToArray } from '../utils/isomorphic/headers'; import { trimStringWithEllipsis } from '../utils/isomorphic/stringUtils'; import { urlMatches, urlMatchesEqual } from '../utils/isomorphic/urlMatch'; @@ -525,11 +525,14 @@ export class Page extends ChannelOwner implements api.Page } async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback', update?: boolean, updateContent?: 'attach' | 'embed', updateMode?: 'minimal' | 'full'} = {}): Promise { + const localUtils = this._connection.localUtils(); + if (!localUtils) + throw new Error('Route from har is not supported in thin clients'); if (options.update) { await this._browserContext._recordIntoHAR(har, this, options); return; } - const harRouter = await HarRouter.create(this._connection.localUtils(), har, options.notFound || 'abort', { urlMatch: options.url }); + const harRouter = await HarRouter.create(localUtils, har, options.notFound || 'abort', { urlMatch: options.url }); this._harRouters.push(harRouter); await harRouter.addPageRoute(this); } diff --git a/packages/playwright-core/src/client/tracing.ts b/packages/playwright-core/src/client/tracing.ts index 61124107fa..5b80f30a0a 100644 --- a/packages/playwright-core/src/client/tracing.ts +++ b/packages/playwright-core/src/client/tracing.ts @@ -69,8 +69,8 @@ export class Tracing extends ChannelOwner implements ap this._isTracing = true; this._connection.setIsTracing(true); } - const result = await this._connection.localUtils().tracingStarted({ tracesDir: this._tracesDir, traceName }); - this._stacksId = result.stacksId; + const result = await this._connection.localUtils()?.tracingStarted({ tracesDir: this._tracesDir, traceName }); + this._stacksId = result?.stacksId; } async stopChunk(options: { path?: string } = {}) { @@ -89,15 +89,19 @@ export class Tracing extends ChannelOwner implements ap // Not interested in artifacts. await this._channel.tracingStopChunk({ mode: 'discard' }); if (this._stacksId) - await this._connection.localUtils().traceDiscarded({ stacksId: this._stacksId }); + await this._connection.localUtils()!.traceDiscarded({ stacksId: this._stacksId }); return; } + const localUtils = this._connection.localUtils(); + if (!localUtils) + throw new Error('Cannot save trace in thin clients'); + const isLocal = !this._connection.isRemote(); if (isLocal) { const result = await this._channel.tracingStopChunk({ mode: 'entries' }); - await this._connection.localUtils().zip({ zipFile: filePath, entries: result.entries!, mode: 'write', stacksId: this._stacksId, includeSources: this._includeSources }); + await localUtils.zip({ zipFile: filePath, entries: result.entries!, mode: 'write', stacksId: this._stacksId, includeSources: this._includeSources }); return; } @@ -106,7 +110,7 @@ export class Tracing extends ChannelOwner implements ap // The artifact may be missing if the browser closed while stopping tracing. if (!result.artifact) { if (this._stacksId) - await this._connection.localUtils().traceDiscarded({ stacksId: this._stacksId }); + await localUtils.traceDiscarded({ stacksId: this._stacksId }); return; } @@ -115,7 +119,7 @@ export class Tracing extends ChannelOwner implements ap await artifact.saveAs(filePath); await artifact.delete(); - await this._connection.localUtils().zip({ zipFile: filePath, entries: [], mode: 'append', stacksId: this._stacksId, includeSources: this._includeSources }); + await localUtils.zip({ zipFile: filePath, entries: [], mode: 'append', stacksId: this._stacksId, includeSources: this._includeSources }); } _resetStackCounter() { diff --git a/packages/playwright-core/src/client/webSocket.ts b/packages/playwright-core/src/client/webSocket.ts new file mode 100644 index 0000000000..cef07a4dfa --- /dev/null +++ b/packages/playwright-core/src/client/webSocket.ts @@ -0,0 +1,116 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChannelOwner } from './channelOwner'; +import { Connection } from './connection'; + +import type { HeadersArray } from './types'; +import type * as channels from '@protocol/channels'; + +export async function connectOverWebSocket(parentConnection: Connection, params: channels.LocalUtilsConnectParams): Promise { + const localUtils = parentConnection.localUtils(); + const transport = localUtils ? new JsonPipeTransport(localUtils) : new WebSocketTransport(); + const connectHeaders = await transport.connect(params); + const connection = new Connection(localUtils, parentConnection.platform, parentConnection._instrumentation, connectHeaders); + connection.markAsRemote(); + connection.on('close', () => transport.close()); + + let closeError: string | undefined; + const onTransportClosed = (reason?: string) => { + connection.close(reason || closeError); + }; + transport.onClose(reason => onTransportClosed(reason)); + connection.onmessage = message => transport.send(message).catch(() => onTransportClosed()); + transport.onMessage(message => { + try { + connection!.dispatch(message); + } catch (e) { + closeError = String(e); + transport.close(); + } + }); + return connection; +} + +interface Transport { + connect(params: channels.LocalUtilsConnectParams): Promise; + send(message: any): Promise; + onMessage(callback: (message: object) => void): void; + onClose(callback: (reason?: string) => void): void; + close(): Promise; +} + +class JsonPipeTransport implements Transport { + private _pipe: channels.JsonPipeChannel | undefined; + private _owner: ChannelOwner; + + constructor(owner: ChannelOwner) { + this._owner = owner; + } + + async connect(params: channels.LocalUtilsConnectParams) { + const { pipe, headers: connectHeaders } = await this._owner._wrapApiCall(async () => { + return await this._owner._channel.connect(params); + }, /* isInternal */ true); + this._pipe = pipe; + return connectHeaders; + } + + async send(message: object) { + this._owner._wrapApiCall(async () => { + await this._pipe!.send({ message }); + }, /* isInternal */ true); + } + + onMessage(callback: (message: object) => void) { + this._pipe!.on('message', ({ message }) => callback(message)); + } + + onClose(callback: (reason?: string) => void) { + this._pipe!.on('closed', ({ reason }) => callback(reason)); + } + + async close() { + await this._owner._wrapApiCall(async () => { + await this._pipe!.close().catch(() => {}); + }, /* isInternal */ true); + } +} + +class WebSocketTransport implements Transport { + private _ws: WebSocket | undefined; + + async connect(params: channels.LocalUtilsConnectParams) { + this._ws = new window.WebSocket(params.wsEndpoint); + return []; + } + + async send(message: object) { + this._ws!.send(JSON.stringify(message)); + } + + onMessage(callback: (message: object) => void) { + this._ws!.addEventListener('message', event => callback(JSON.parse(event.data))); + } + + onClose(callback: (reason?: string) => void) { + this._ws!.addEventListener('close', () => callback()); + } + + async close() { + this._ws!.close(); + } +} diff --git a/packages/playwright-core/src/common/DEPS.list b/packages/playwright-core/src/common/DEPS.list index a25dd41c36..686b88087b 100644 --- a/packages/playwright-core/src/common/DEPS.list +++ b/packages/playwright-core/src/common/DEPS.list @@ -1,5 +1,2 @@ [*] -../utils/ ../utils/isomorphic/ -../utilsBundle.ts -../zipBundle.ts diff --git a/packages/playwright-core/src/common/platform.ts b/packages/playwright-core/src/common/platform.ts index bb73ec6d31..330b5d6323 100644 --- a/packages/playwright-core/src/common/platform.ts +++ b/packages/playwright-core/src/common/platform.ts @@ -14,12 +14,10 @@ * limitations under the License. */ -import * as crypto from 'crypto'; -import * as fs from 'fs'; -import * as path from 'path'; - import { webColors, noColors } from '../utils/isomorphic/colors'; +import type * as fs from 'fs'; +import type * as path from 'path'; import type { Colors } from '../utils/isomorphic/colors'; export type Zone = { @@ -37,6 +35,8 @@ const noopZone: Zone = { }; export type Platform = { + name: 'node' | 'web' | 'empty'; + calculateSha1(text: string): Promise; colors: Colors; createGuid: () => string; @@ -46,21 +46,22 @@ export type Platform = { log(name: 'api' | 'channel', message: string | Error | object): void; path: () => typeof path; pathSeparator: string; - ws?: (url: string) => WebSocket; zones: { empty: Zone, current: () => Zone; }; }; export const webPlatform: Platform = { + name: 'web', + calculateSha1: async (text: string) => { const bytes = new TextEncoder().encode(text); - const hashBuffer = await crypto.subtle.digest('SHA-1', bytes); + const hashBuffer = await window.crypto.subtle.digest('SHA-1', bytes); return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join(''); }, colors: webColors, createGuid: () => { - return Array.from(crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join(''); + return Array.from(window.crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join(''); }, fs: () => { @@ -82,12 +83,12 @@ export const webPlatform: Platform = { pathSeparator: '/', - ws: (url: string) => new WebSocket(url), - zones: { empty: noopZone, current: () => noopZone }, }; export const emptyPlatform: Platform = { + name: 'empty', + calculateSha1: async () => { throw new Error('Not implemented'); }, diff --git a/packages/playwright-core/src/common/progress.ts b/packages/playwright-core/src/common/progress.ts deleted file mode 100644 index f09670e823..0000000000 --- a/packages/playwright-core/src/common/progress.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export interface Progress { - log(message: string): void; - timeUntilDeadline(): number; - isRunning(): boolean; - cleanupWhenAborted(cleanup: () => any): void; - throwIfAborted(): void; -} diff --git a/packages/playwright-core/src/protocol/DEPS.list b/packages/playwright-core/src/protocol/DEPS.list index bf64b324f1..dbdeafe86c 100644 --- a/packages/playwright-core/src/protocol/DEPS.list +++ b/packages/playwright-core/src/protocol/DEPS.list @@ -1,4 +1,3 @@ [*] ../common/ -../utils/ - +../utils/isomorphic diff --git a/packages/playwright-core/src/protocol/validatorPrimitives.ts b/packages/playwright-core/src/protocol/validatorPrimitives.ts index 9d4614512b..f57a63acea 100644 --- a/packages/playwright-core/src/protocol/validatorPrimitives.ts +++ b/packages/playwright-core/src/protocol/validatorPrimitives.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { isUnderTest } from '../utils'; +import { isUnderTest } from '../utils/isomorphic/debug'; export class ValidationError extends Error {} export type Validator = (arg: any, path: string, context: ValidatorContext) => any; diff --git a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts index b582aa8788..1c74b7258c 100644 --- a/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/localUtilsDispatcher.ts @@ -16,8 +16,7 @@ import { Dispatcher } from './dispatcher'; import { SdkObject } from '../../server/instrumentation'; -import * as localUtils from '../../common/localUtils'; -import { nodePlatform } from '../utils/nodePlatform'; +import * as localUtils from '../localUtils'; import { getUserAgent } from '../utils/userAgent'; import { deviceDescriptors as descriptors } from '../deviceDescriptors'; import { JsonPipeDispatcher } from '../dispatchers/jsonPipeDispatcher'; @@ -26,7 +25,7 @@ import { SocksInterceptor } from '../socksInterceptor'; import { WebSocketTransport } from '../transport'; import { fetchData } from '../utils/network'; -import type { HarBackend } from '../../common/harBackend'; +import type { HarBackend } from '../harBackend'; import type { CallMetadata } from '../instrumentation'; import type { Playwright } from '../playwright'; import type { RootDispatcher } from './dispatcher'; @@ -50,11 +49,11 @@ export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels. } async zip(params: channels.LocalUtilsZipParams): Promise { - return await localUtils.zip(nodePlatform, this._stackSessions, params); + return await localUtils.zip(this._stackSessions, params); } async harOpen(params: channels.LocalUtilsHarOpenParams, metadata: CallMetadata): Promise { - return await localUtils.harOpen(nodePlatform, this._harBackends, params); + return await localUtils.harOpen(this._harBackends, params); } async harLookup(params: channels.LocalUtilsHarLookupParams, metadata: CallMetadata): Promise { @@ -74,7 +73,7 @@ export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels. } async traceDiscarded(params: channels.LocalUtilsTraceDiscardedParams, metadata?: CallMetadata | undefined): Promise { - return await localUtils.traceDiscarded(nodePlatform, this._stackSessions, params); + return await localUtils.traceDiscarded(this._stackSessions, params); } async addStackToTracingNoReply(params: channels.LocalUtilsAddStackToTracingNoReplyParams, metadata?: CallMetadata | undefined): Promise { diff --git a/packages/playwright-core/src/server/fileUploadUtils.ts b/packages/playwright-core/src/server/fileUploadUtils.ts index 908e7644ac..5a15617c8b 100644 --- a/packages/playwright-core/src/server/fileUploadUtils.ts +++ b/packages/playwright-core/src/server/fileUploadUtils.ts @@ -18,7 +18,6 @@ import * as fs from 'fs'; import * as path from 'path'; import { assert } from '../utils/isomorphic/debug'; -import { fileUploadSizeLimit } from '../common/fileUtils'; import { mime } from '../utilsBundle'; import type { WritableStreamDispatcher } from './dispatchers/writableStreamDispatcher'; @@ -27,6 +26,9 @@ import type { Frame } from './frames'; import type * as types from './types'; import type * as channels from '@protocol/channels'; +// Keep in sync with the client. +export const fileUploadSizeLimit = 50 * 1024 * 1024; + async function filesExceedUploadLimit(files: string[]) { const sizes = await Promise.all(files.map(async file => (await fs.promises.stat(file)).size)); return sizes.reduce((total, size) => total + size, 0) >= fileUploadSizeLimit; diff --git a/packages/playwright-core/src/common/harBackend.ts b/packages/playwright-core/src/server/harBackend.ts similarity index 92% rename from packages/playwright-core/src/common/harBackend.ts rename to packages/playwright-core/src/server/harBackend.ts index f59b7de5f1..0814be9c5f 100644 --- a/packages/playwright-core/src/common/harBackend.ts +++ b/packages/playwright-core/src/server/harBackend.ts @@ -14,11 +14,14 @@ * limitations under the License. */ -import { ZipFile } from '../utils/zipFile'; +import * as fs from 'fs'; +import * as path from 'path'; -import type { HeadersArray } from './types'; +import { createGuid } from './utils/crypto'; +import { ZipFile } from './utils/zipFile'; + +import type { HeadersArray } from '../common/types'; import type * as har from '@trace/har'; -import type { Platform } from './platform'; const redirectStatus = [301, 302, 303, 307, 308]; @@ -27,11 +30,9 @@ export class HarBackend { private _harFile: har.HARFile; private _zipFile: ZipFile | null; private _baseDir: string | null; - private _platform: Platform; - constructor(platform: Platform, harFile: har.HARFile, baseDir: string | null, zipFile: ZipFile | null) { - this._platform = platform; - this.id = platform.createGuid(); + constructor(harFile: har.HARFile, baseDir: string | null, zipFile: ZipFile | null) { + this.id = createGuid(); this._harFile = harFile; this._baseDir = baseDir; this._zipFile = zipFile; @@ -79,7 +80,7 @@ export class HarBackend { if (this._zipFile) buffer = await this._zipFile.read(file); else - buffer = await this._platform.fs().promises.readFile(this._platform.path().resolve(this._baseDir!, file)); + buffer = await fs.promises.readFile(path.resolve(this._baseDir!, file)); } else { buffer = Buffer.from(content.text || '', content.encoding === 'base64' ? 'base64' : 'utf-8'); } diff --git a/packages/playwright-core/src/common/localUtils.ts b/packages/playwright-core/src/server/localUtils.ts similarity index 84% rename from packages/playwright-core/src/common/localUtils.ts rename to packages/playwright-core/src/server/localUtils.ts index 5020d82b75..1f5f0064b5 100644 --- a/packages/playwright-core/src/common/localUtils.ts +++ b/packages/playwright-core/src/server/localUtils.ts @@ -18,15 +18,15 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { removeFolders } from './fileUtils'; +import { calculateSha1 } from './utils/crypto'; import { HarBackend } from './harBackend'; import { ManualPromise } from '../utils/isomorphic/manualPromise'; -import { ZipFile } from '../utils/zipFile'; +import { ZipFile } from './utils/zipFile'; import { yauzl, yazl } from '../zipBundle'; import { serializeClientSideCallMetadata } from '../utils/isomorphic/traceUtils'; import { assert } from '../utils/isomorphic/debug'; +import { removeFolders } from './utils/fileUtils'; -import type { Platform } from './platform'; import type * as channels from '@protocol/channels'; import type * as har from '@trace/har'; import type EventEmitter from 'events'; @@ -39,7 +39,7 @@ export type StackSession = { callStacks: channels.ClientSideCallMetadata[]; }; -export async function zip(platform: Platform, stackSessions: Map, params: channels.LocalUtilsZipParams): Promise { +export async function zip(stackSessions: Map, params: channels.LocalUtilsZipParams): Promise { const promise = new ManualPromise(); const zipFile = new yazl.ZipFile(); (zipFile as any as EventEmitter).on('error', error => promise.reject(error)); @@ -77,7 +77,7 @@ export async function zip(platform: Platform, stackSessions: Map promise.reject(error)); }); await promise; - await deleteStackSession(platform, stackSessions, params.stacksId); + await deleteStackSession(stackSessions, params.stacksId); return; } @@ -124,20 +124,20 @@ export async function zip(platform: Platform, stackSessions: Map, stacksId?: string) { +async function deleteStackSession(stackSessions: Map, stacksId?: string) { const session = stacksId ? stackSessions.get(stacksId) : undefined; if (!session) return; await session.writer; if (session.tmpDir) - await removeFolders(platform, [session.tmpDir]); + await removeFolders([session.tmpDir]); stackSessions.delete(stacksId!); } -export async function harOpen(platform: Platform, harBackends: Map, params: channels.LocalUtilsHarOpenParams): Promise { +export async function harOpen(harBackends: Map, params: channels.LocalUtilsHarOpenParams): Promise { let harBackend: HarBackend; if (params.file.endsWith('.zip')) { const zipFile = new ZipFile(params.file); @@ -147,10 +147,10 @@ export async function harOpen(platform: Platform, harBackends: Map, p return { stacksId: traceStacksFile }; } -export async function traceDiscarded(platform: Platform, stackSessions: Map, params: channels.LocalUtilsTraceDiscardedParams): Promise { - await deleteStackSession(platform, stackSessions, params.stacksId); +export async function traceDiscarded(stackSessions: Map, params: channels.LocalUtilsTraceDiscardedParams): Promise { + await deleteStackSession(stackSessions, params.stacksId); } export async function addStackToTracingNoReply(stackSessions: Map, params: channels.LocalUtilsAddStackToTracingNoReplyParams): Promise { diff --git a/packages/playwright-core/src/server/progress.ts b/packages/playwright-core/src/server/progress.ts index 30db144fbb..16dcc6fb1f 100644 --- a/packages/playwright-core/src/server/progress.ts +++ b/packages/playwright-core/src/server/progress.ts @@ -19,10 +19,14 @@ import { assert, monotonicTime } from '../utils'; import { ManualPromise } from '../utils/isomorphic/manualPromise'; import type { CallMetadata, Instrumentation, SdkObject } from './instrumentation'; -import type { Progress as CommonProgress } from '../common/progress'; import type { LogName } from './utils/debugLogger'; -export interface Progress extends CommonProgress { +export interface Progress { + log(message: string): void; + timeUntilDeadline(): number; + isRunning(): boolean; + cleanupWhenAborted(cleanup: () => any): void; + throwIfAborted(): void; metadata: CallMetadata; } diff --git a/packages/playwright-core/src/server/utils/nodePlatform.ts b/packages/playwright-core/src/server/utils/nodePlatform.ts index 49f6b23ffe..1c2a4dad0c 100644 --- a/packages/playwright-core/src/server/utils/nodePlatform.ts +++ b/packages/playwright-core/src/server/utils/nodePlatform.ts @@ -45,16 +45,14 @@ class NodeZone implements Zone { return this._zone.run(func); } - runIgnoreCurrent(func: () => R): R { - return emptyZone.run(func); - } - data(): T | undefined { return this._zone.data('apiZone'); } } export const nodePlatform: Platform = { + name: 'node', + calculateSha1: (text: string) => { const sha1 = crypto.createHash('sha1'); sha1.update(text); diff --git a/packages/playwright-core/src/utils/zipFile.ts b/packages/playwright-core/src/server/utils/zipFile.ts similarity index 95% rename from packages/playwright-core/src/utils/zipFile.ts rename to packages/playwright-core/src/server/utils/zipFile.ts index 1f70c5e1bc..43b5a3430c 100644 --- a/packages/playwright-core/src/utils/zipFile.ts +++ b/packages/playwright-core/src/server/utils/zipFile.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { yauzl } from '../zipBundle'; +import { yauzl } from '../../zipBundle'; -import type { Entry, UnzipFile } from '../zipBundle'; +import type { Entry, UnzipFile } from '../../zipBundle'; export class ZipFile { private _fileName: string; diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index 839aa390a8..dc5f284955 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -29,7 +29,6 @@ export * from './utils/isomorphic/urlMatch'; export * from './utils/isomorphic/headers'; export * from './utils/isomorphic/semaphore'; export * from './utils/isomorphic/stackTrace'; -export * from './utils/zipFile'; export * from './server/utils/ascii'; export * from './server/utils/comparators'; @@ -50,6 +49,7 @@ export * from './server/utils/spawnAsync'; export * from './server/utils/task'; export * from './server/utils/userAgent'; export * from './server/utils/wsServer'; +export * from './server/utils/zipFile'; export * from './server/utils/zones'; export { colors } from './utilsBundle'; diff --git a/packages/playwright-core/src/utils/isomorphic/mimeType.ts b/packages/playwright-core/src/utils/isomorphic/mimeType.ts index 407d935281..45ac92d645 100644 --- a/packages/playwright-core/src/utils/isomorphic/mimeType.ts +++ b/packages/playwright-core/src/utils/isomorphic/mimeType.ts @@ -1,14 +1,14 @@ /** * Copyright (c) Microsoft Corporation. * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -21,3 +21,426 @@ export function isJsonMimeType(mimeType: string) { export function isTextualMimeType(mimeType: string) { return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/); } +export function getMimeTypeForPath(path: string): string | null { + const dotIndex = path.lastIndexOf('.'); + if (dotIndex === -1) + return null; + const extension = path.substring(dotIndex + 1); + return types.get(extension) || null; +} + +const types: Map = new Map([ + ['ez', 'application/andrew-inset'], + ['aw', 'application/applixware'], + ['atom', 'application/atom+xml'], + ['atomcat', 'application/atomcat+xml'], + ['atomdeleted', 'application/atomdeleted+xml'], + ['atomsvc', 'application/atomsvc+xml'], + ['dwd', 'application/atsc-dwd+xml'], + ['held', 'application/atsc-held+xml'], + ['rsat', 'application/atsc-rsat+xml'], + ['bdoc', 'application/bdoc'], + ['xcs', 'application/calendar+xml'], + ['ccxml', 'application/ccxml+xml'], + ['cdfx', 'application/cdfx+xml'], + ['cdmia', 'application/cdmi-capability'], + ['cdmic', 'application/cdmi-container'], + ['cdmid', 'application/cdmi-domain'], + ['cdmio', 'application/cdmi-object'], + ['cdmiq', 'application/cdmi-queue'], + ['cu', 'application/cu-seeme'], + ['mpd', 'application/dash+xml'], + ['davmount', 'application/davmount+xml'], + ['dbk', 'application/docbook+xml'], + ['dssc', 'application/dssc+der'], + ['xdssc', 'application/dssc+xml'], + ['ecma', 'application/ecmascript'], + ['es', 'application/ecmascript'], + ['emma', 'application/emma+xml'], + ['emotionml', 'application/emotionml+xml'], + ['epub', 'application/epub+zip'], + ['exi', 'application/exi'], + ['exp', 'application/express'], + ['fdt', 'application/fdt+xml'], + ['pfr', 'application/font-tdpfr'], + ['geojson', 'application/geo+json'], + ['gml', 'application/gml+xml'], + ['gpx', 'application/gpx+xml'], + ['gxf', 'application/gxf'], + ['gz', 'application/gzip'], + ['hjson', 'application/hjson'], + ['stk', 'application/hyperstudio'], + ['ink', 'application/inkml+xml'], + ['inkml', 'application/inkml+xml'], + ['ipfix', 'application/ipfix'], + ['its', 'application/its+xml'], + ['ear', 'application/java-archive'], + ['jar', 'application/java-archive'], + ['war', 'application/java-archive'], + ['ser', 'application/java-serialized-object'], + ['class', 'application/java-vm'], + ['js', 'application/javascript'], + ['mjs', 'application/javascript'], + ['json', 'application/json'], + ['map', 'application/json'], + ['json5', 'application/json5'], + ['jsonml', 'application/jsonml+json'], + ['jsonld', 'application/ld+json'], + ['lgr', 'application/lgr+xml'], + ['lostxml', 'application/lost+xml'], + ['hqx', 'application/mac-binhex40'], + ['cpt', 'application/mac-compactpro'], + ['mads', 'application/mads+xml'], + ['webmanifest', 'application/manifest+json'], + ['mrc', 'application/marc'], + ['mrcx', 'application/marcxml+xml'], + ['ma', 'application/mathematica'], + ['mb', 'application/mathematica'], + ['nb', 'application/mathematica'], + ['mathml', 'application/mathml+xml'], + ['mbox', 'application/mbox'], + ['mscml', 'application/mediaservercontrol+xml'], + ['metalink', 'application/metalink+xml'], + ['meta4', 'application/metalink4+xml'], + ['mets', 'application/mets+xml'], + ['maei', 'application/mmt-aei+xml'], + ['musd', 'application/mmt-usd+xml'], + ['mods', 'application/mods+xml'], + ['m21', 'application/mp21'], + ['mp21', 'application/mp21'], + ['m4p', 'application/mp4'], + ['mp4s', 'application/mp4'], + ['doc', 'application/msword'], + ['dot', 'application/msword'], + ['mxf', 'application/mxf'], + ['nq', 'application/n-quads'], + ['nt', 'application/n-triples'], + ['cjs', 'application/node'], + ['bin', 'application/octet-stream'], + ['bpk', 'application/octet-stream'], + ['buffer', 'application/octet-stream'], + ['deb', 'application/octet-stream'], + ['deploy', 'application/octet-stream'], + ['dist', 'application/octet-stream'], + ['distz', 'application/octet-stream'], + ['dll', 'application/octet-stream'], + ['dmg', 'application/octet-stream'], + ['dms', 'application/octet-stream'], + ['dump', 'application/octet-stream'], + ['elc', 'application/octet-stream'], + ['exe', 'application/octet-stream'], + ['img', 'application/octet-stream'], + ['iso', 'application/octet-stream'], + ['lrf', 'application/octet-stream'], + ['mar', 'application/octet-stream'], + ['msi', 'application/octet-stream'], + ['msm', 'application/octet-stream'], + ['msp', 'application/octet-stream'], + ['pkg', 'application/octet-stream'], + ['so', 'application/octet-stream'], + ['oda', 'application/oda'], + ['opf', 'application/oebps-package+xml'], + ['ogx', 'application/ogg'], + ['omdoc', 'application/omdoc+xml'], + ['onepkg', 'application/onenote'], + ['onetmp', 'application/onenote'], + ['onetoc', 'application/onenote'], + ['onetoc2', 'application/onenote'], + ['oxps', 'application/oxps'], + ['relo', 'application/p2p-overlay+xml'], + ['xer', 'application/patch-ops-error+xml'], + ['pdf', 'application/pdf'], + ['pgp', 'application/pgp-encrypted'], + ['asc', 'application/pgp-signature'], + ['sig', 'application/pgp-signature'], + ['prf', 'application/pics-rules'], + ['p10', 'application/pkcs10'], + ['p7c', 'application/pkcs7-mime'], + ['p7m', 'application/pkcs7-mime'], + ['p7s', 'application/pkcs7-signature'], + ['p8', 'application/pkcs8'], + ['ac', 'application/pkix-attr-cert'], + ['cer', 'application/pkix-cert'], + ['crl', 'application/pkix-crl'], + ['pkipath', 'application/pkix-pkipath'], + ['pki', 'application/pkixcmp'], + ['pls', 'application/pls+xml'], + ['ai', 'application/postscript'], + ['eps', 'application/postscript'], + ['ps', 'application/postscript'], + ['provx', 'application/provenance+xml'], + ['pskcxml', 'application/pskc+xml'], + ['raml', 'application/raml+yaml'], + ['owl', 'application/rdf+xml'], + ['rdf', 'application/rdf+xml'], + ['rif', 'application/reginfo+xml'], + ['rnc', 'application/relax-ng-compact-syntax'], + ['rl', 'application/resource-lists+xml'], + ['rld', 'application/resource-lists-diff+xml'], + ['rs', 'application/rls-services+xml'], + ['rapd', 'application/route-apd+xml'], + ['sls', 'application/route-s-tsid+xml'], + ['rusd', 'application/route-usd+xml'], + ['gbr', 'application/rpki-ghostbusters'], + ['mft', 'application/rpki-manifest'], + ['roa', 'application/rpki-roa'], + ['rsd', 'application/rsd+xml'], + ['rss', 'application/rss+xml'], + ['rtf', 'application/rtf'], + ['sbml', 'application/sbml+xml'], + ['scq', 'application/scvp-cv-request'], + ['scs', 'application/scvp-cv-response'], + ['spq', 'application/scvp-vp-request'], + ['spp', 'application/scvp-vp-response'], + ['sdp', 'application/sdp'], + ['senmlx', 'application/senml+xml'], + ['sensmlx', 'application/sensml+xml'], + ['setpay', 'application/set-payment-initiation'], + ['setreg', 'application/set-registration-initiation'], + ['shf', 'application/shf+xml'], + ['sieve', 'application/sieve'], + ['siv', 'application/sieve'], + ['smi', 'application/smil+xml'], + ['smil', 'application/smil+xml'], + ['rq', 'application/sparql-query'], + ['srx', 'application/sparql-results+xml'], + ['gram', 'application/srgs'], + ['grxml', 'application/srgs+xml'], + ['sru', 'application/sru+xml'], + ['ssdl', 'application/ssdl+xml'], + ['ssml', 'application/ssml+xml'], + ['swidtag', 'application/swid+xml'], + ['tei', 'application/tei+xml'], + ['teicorpus', 'application/tei+xml'], + ['tfi', 'application/thraud+xml'], + ['tsd', 'application/timestamped-data'], + ['toml', 'application/toml'], + ['trig', 'application/trig'], + ['ttml', 'application/ttml+xml'], + ['ubj', 'application/ubjson'], + ['rsheet', 'application/urc-ressheet+xml'], + ['td', 'application/urc-targetdesc+xml'], + ['vxml', 'application/voicexml+xml'], + ['wasm', 'application/wasm'], + ['wgt', 'application/widget'], + ['hlp', 'application/winhlp'], + ['wsdl', 'application/wsdl+xml'], + ['wspolicy', 'application/wspolicy+xml'], + ['xaml', 'application/xaml+xml'], + ['xav', 'application/xcap-att+xml'], + ['xca', 'application/xcap-caps+xml'], + ['xdf', 'application/xcap-diff+xml'], + ['xel', 'application/xcap-el+xml'], + ['xns', 'application/xcap-ns+xml'], + ['xenc', 'application/xenc+xml'], + ['xht', 'application/xhtml+xml'], + ['xhtml', 'application/xhtml+xml'], + ['xlf', 'application/xliff+xml'], + ['rng', 'application/xml'], + ['xml', 'application/xml'], + ['xsd', 'application/xml'], + ['xsl', 'application/xml'], + ['dtd', 'application/xml-dtd'], + ['xop', 'application/xop+xml'], + ['xpl', 'application/xproc+xml'], + ['*xsl', 'application/xslt+xml'], + ['xslt', 'application/xslt+xml'], + ['xspf', 'application/xspf+xml'], + ['mxml', 'application/xv+xml'], + ['xhvml', 'application/xv+xml'], + ['xvm', 'application/xv+xml'], + ['xvml', 'application/xv+xml'], + ['yang', 'application/yang'], + ['yin', 'application/yin+xml'], + ['zip', 'application/zip'], + ['*3gpp', 'audio/3gpp'], + ['adp', 'audio/adpcm'], + ['amr', 'audio/amr'], + ['au', 'audio/basic'], + ['snd', 'audio/basic'], + ['kar', 'audio/midi'], + ['mid', 'audio/midi'], + ['midi', 'audio/midi'], + ['rmi', 'audio/midi'], + ['mxmf', 'audio/mobile-xmf'], + ['*mp3', 'audio/mp3'], + ['m4a', 'audio/mp4'], + ['mp4a', 'audio/mp4'], + ['m2a', 'audio/mpeg'], + ['m3a', 'audio/mpeg'], + ['mp2', 'audio/mpeg'], + ['mp2a', 'audio/mpeg'], + ['mp3', 'audio/mpeg'], + ['mpga', 'audio/mpeg'], + ['oga', 'audio/ogg'], + ['ogg', 'audio/ogg'], + ['opus', 'audio/ogg'], + ['spx', 'audio/ogg'], + ['s3m', 'audio/s3m'], + ['sil', 'audio/silk'], + ['wav', 'audio/wav'], + ['*wav', 'audio/wave'], + ['weba', 'audio/webm'], + ['xm', 'audio/xm'], + ['ttc', 'font/collection'], + ['otf', 'font/otf'], + ['ttf', 'font/ttf'], + ['woff', 'font/woff'], + ['woff2', 'font/woff2'], + ['exr', 'image/aces'], + ['apng', 'image/apng'], + ['avif', 'image/avif'], + ['bmp', 'image/bmp'], + ['cgm', 'image/cgm'], + ['drle', 'image/dicom-rle'], + ['emf', 'image/emf'], + ['fits', 'image/fits'], + ['g3', 'image/g3fax'], + ['gif', 'image/gif'], + ['heic', 'image/heic'], + ['heics', 'image/heic-sequence'], + ['heif', 'image/heif'], + ['heifs', 'image/heif-sequence'], + ['hej2', 'image/hej2k'], + ['hsj2', 'image/hsj2'], + ['ief', 'image/ief'], + ['jls', 'image/jls'], + ['jp2', 'image/jp2'], + ['jpg2', 'image/jp2'], + ['jpe', 'image/jpeg'], + ['jpeg', 'image/jpeg'], + ['jpg', 'image/jpeg'], + ['jph', 'image/jph'], + ['jhc', 'image/jphc'], + ['jpm', 'image/jpm'], + ['jpf', 'image/jpx'], + ['jpx', 'image/jpx'], + ['jxr', 'image/jxr'], + ['jxra', 'image/jxra'], + ['jxrs', 'image/jxrs'], + ['jxs', 'image/jxs'], + ['jxsc', 'image/jxsc'], + ['jxsi', 'image/jxsi'], + ['jxss', 'image/jxss'], + ['ktx', 'image/ktx'], + ['ktx2', 'image/ktx2'], + ['png', 'image/png'], + ['sgi', 'image/sgi'], + ['svg', 'image/svg+xml'], + ['svgz', 'image/svg+xml'], + ['t38', 'image/t38'], + ['tif', 'image/tiff'], + ['tiff', 'image/tiff'], + ['tfx', 'image/tiff-fx'], + ['webp', 'image/webp'], + ['wmf', 'image/wmf'], + ['disposition-notification', 'message/disposition-notification'], + ['u8msg', 'message/global'], + ['u8dsn', 'message/global-delivery-status'], + ['u8mdn', 'message/global-disposition-notification'], + ['u8hdr', 'message/global-headers'], + ['eml', 'message/rfc822'], + ['mime', 'message/rfc822'], + ['3mf', 'model/3mf'], + ['gltf', 'model/gltf+json'], + ['glb', 'model/gltf-binary'], + ['iges', 'model/iges'], + ['igs', 'model/iges'], + ['mesh', 'model/mesh'], + ['msh', 'model/mesh'], + ['silo', 'model/mesh'], + ['mtl', 'model/mtl'], + ['obj', 'model/obj'], + ['stpx', 'model/step+xml'], + ['stpz', 'model/step+zip'], + ['stpxz', 'model/step-xml+zip'], + ['stl', 'model/stl'], + ['vrml', 'model/vrml'], + ['wrl', 'model/vrml'], + ['*x3db', 'model/x3d+binary'], + ['x3dbz', 'model/x3d+binary'], + ['x3db', 'model/x3d+fastinfoset'], + ['*x3dv', 'model/x3d+vrml'], + ['x3dvz', 'model/x3d+vrml'], + ['x3d', 'model/x3d+xml'], + ['x3dz', 'model/x3d+xml'], + ['x3dv', 'model/x3d-vrml'], + ['appcache', 'text/cache-manifest'], + ['manifest', 'text/cache-manifest'], + ['ics', 'text/calendar'], + ['ifb', 'text/calendar'], + ['coffee', 'text/coffeescript'], + ['litcoffee', 'text/coffeescript'], + ['css', 'text/css'], + ['csv', 'text/csv'], + ['htm', 'text/html'], + ['html', 'text/html'], + ['shtml', 'text/html'], + ['jade', 'text/jade'], + ['jsx', 'text/jsx'], + ['less', 'text/less'], + ['markdown', 'text/markdown'], + ['md', 'text/markdown'], + ['mml', 'text/mathml'], + ['mdx', 'text/mdx'], + ['n3', 'text/n3'], + ['conf', 'text/plain'], + ['def', 'text/plain'], + ['in', 'text/plain'], + ['ini', 'text/plain'], + ['list', 'text/plain'], + ['log', 'text/plain'], + ['text', 'text/plain'], + ['txt', 'text/plain'], + ['rtx', 'text/richtext'], + ['*rtf', 'text/rtf'], + ['sgm', 'text/sgml'], + ['sgml', 'text/sgml'], + ['shex', 'text/shex'], + ['slim', 'text/slim'], + ['slm', 'text/slim'], + ['spdx', 'text/spdx'], + ['styl', 'text/stylus'], + ['stylus', 'text/stylus'], + ['tsv', 'text/tab-separated-values'], + ['man', 'text/troff'], + ['me', 'text/troff'], + ['ms', 'text/troff'], + ['roff', 'text/troff'], + ['t', 'text/troff'], + ['tr', 'text/troff'], + ['ttl', 'text/turtle'], + ['uri', 'text/uri-list'], + ['uris', 'text/uri-list'], + ['urls', 'text/uri-list'], + ['vcard', 'text/vcard'], + ['vtt', 'text/vtt'], + ['*xml', 'text/xml'], + ['yaml', 'text/yaml'], + ['yml', 'text/yaml'], + ['3gp', 'video/3gpp'], + ['3gpp', 'video/3gpp'], + ['3g2', 'video/3gpp2'], + ['h261', 'video/h261'], + ['h263', 'video/h263'], + ['h264', 'video/h264'], + ['m4s', 'video/iso.segment'], + ['jpgv', 'video/jpeg'], + ['jpm', 'video/jpm'], + ['jpgm', 'video/jpm'], + ['mj2', 'video/mj2'], + ['mjp2', 'video/mj2'], + ['ts', 'video/mp2t'], + ['mp4', 'video/mp4'], + ['mp4v', 'video/mp4'], + ['mpg4', 'video/mp4'], + ['m1v', 'video/mpeg'], + ['m2v', 'video/mpeg'], + ['mpe', 'video/mpeg'], + ['mpeg', 'video/mpeg'], + ['mpg', 'video/mpeg'], + ['ogv', 'video/ogg'], + ['mov', 'video/quicktime'], + ['qt', 'video/quicktime'], + ['webm', 'video/webm'] +]); diff --git a/tests/config/utils.ts b/tests/config/utils.ts index 3743e97d80..3ab51c9290 100644 --- a/tests/config/utils.ts +++ b/tests/config/utils.ts @@ -15,7 +15,7 @@ */ import type { Frame, Page } from 'playwright-core'; -import { ZipFile } from '../../packages/playwright-core/lib/utils/zipFile'; +import { ZipFile } from '../../packages/playwright-core/lib/server/utils/zipFile'; import type { TraceModelBackend } from '../../packages/trace-viewer/src/sw/traceModel'; import type { StackFrame } from '../../packages/protocol/src/channels'; import { parseClientSideCallMetadata } from '../../packages/playwright-core/lib/utils/isomorphic/traceUtils'; From 6833b664e373b3137e7789aaaccd7fcf388b4bba Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 13 Feb 2025 16:37:15 -0800 Subject: [PATCH 12/13] test: update modernizr expectations with actual mobile Safari 18.3 values (#34789) --- tests/assets/modernizr/README.md | 4 ++-- tests/assets/modernizr/mobile-safari-18.json | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/assets/modernizr/README.md b/tests/assets/modernizr/README.md index bf3241283d..2a986d23d4 100644 --- a/tests/assets/modernizr/README.md +++ b/tests/assets/modernizr/README.md @@ -7,8 +7,8 @@ ## Updating expectations -1. `npx http-server .` -1. Navigate to `http://127.0.0.1:8080/tests/assets/modernizr/index.html` +1. Serve `tests/assets/modernizr/index.html` from a remote (localhost results will be different) https origin (e.g. https://pages.github.com). +1. Navigate to `https://your-domain.com/tests/assets/modernizr/index.html` Do this with: diff --git a/tests/assets/modernizr/mobile-safari-18.json b/tests/assets/modernizr/mobile-safari-18.json index e86fc3de20..cd2822a65c 100644 --- a/tests/assets/modernizr/mobile-safari-18.json +++ b/tests/assets/modernizr/mobile-safari-18.json @@ -362,6 +362,7 @@ "EXT_polygon_offset_clamp": true, "EXT_shader_texture_lod": true, "EXT_texture_filter_anisotropic": true, + "EXT_texture_mirror_clamp_to_edge": true, "EXT_sRGB": true, "KHR_parallel_shader_compile": true, "OES_element_index_uint": true, @@ -371,6 +372,7 @@ "OES_texture_half_float": true, "OES_texture_half_float_linear": true, "OES_vertex_array_object": true, + "WEBGL_blend_func_extended": true, "WEBGL_color_buffer_float": true, "WEBGL_compressed_texture_astc": true, "WEBGL_compressed_texture_etc": true, From 4a9b3361689a4a18db23a743c7c3b56fefdb35cf Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 13 Feb 2025 16:46:24 -0800 Subject: [PATCH 13/13] chore: for not use Node's events in client (#34791) --- packages/playwright-core/src/client/android.ts | 3 +-- packages/playwright-core/src/client/browserType.ts | 4 +--- packages/playwright-core/src/client/connection.ts | 2 +- packages/playwright-core/src/client/eventEmitter.ts | 10 +++++++--- packages/playwright-core/src/client/frame.ts | 3 +-- packages/playwright-core/src/client/network.ts | 2 -- packages/playwright-core/src/client/page.ts | 2 +- packages/playwright-core/src/common/platform.ts | 4 ++++ packages/playwright-core/src/inProcessFactory.ts | 5 ++++- .../playwright-core/src/server/utils/nodePlatform.ts | 2 ++ 10 files changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/playwright-core/src/client/android.ts b/packages/playwright-core/src/client/android.ts index 3aedc5c4ac..134be7c7bb 100644 --- a/packages/playwright-core/src/client/android.ts +++ b/packages/playwright-core/src/client/android.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { EventEmitter } from 'events'; - +import { EventEmitter } from './eventEmitter'; import { BrowserContext, prepareBrowserContextParams } from './browserContext'; import { ChannelOwner } from './channelOwner'; import { TargetClosedError, isTargetClosedError } from './errors'; diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index 39a9a3f1cc..e4942bd7f0 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import path from 'path'; - import { Browser } from './browser'; import { BrowserContext, prepareBrowserContextParams } from './browserContext'; import { ChannelOwner } from './channelOwner'; @@ -101,7 +99,7 @@ export class BrowserType extends ChannelOwner imple ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs), env: options.env ? envObjectToArray(options.env) : undefined, channel: options.channel, - userDataDir: (path.isAbsolute(userDataDir) || !userDataDir) ? userDataDir : path.resolve(userDataDir), + userDataDir: (this._platform.path().isAbsolute(userDataDir) || !userDataDir) ? userDataDir : this._platform.path().resolve(userDataDir), }; return await this._wrapApiCall(async () => { const result = await this._channel.launchPersistentContext(persistentParams); diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts index 929acff25f..9f2745a8ec 100644 --- a/packages/playwright-core/src/client/connection.ts +++ b/packages/playwright-core/src/client/connection.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { EventEmitter } from 'events'; +import { EventEmitter } from './eventEmitter'; import { Android, AndroidDevice, AndroidSocket } from './android'; import { Artifact } from './artifact'; import { Browser } from './browser'; diff --git a/packages/playwright-core/src/client/eventEmitter.ts b/packages/playwright-core/src/client/eventEmitter.ts index ce695490c2..a0781534e3 100644 --- a/packages/playwright-core/src/client/eventEmitter.ts +++ b/packages/playwright-core/src/client/eventEmitter.ts @@ -22,8 +22,6 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { EventEmitter as OriginalEventEmitter } from 'events'; - import { isUnderTest } from '../utils/isomorphic/debug'; import type { EventEmitter as EventEmitterType } from 'events'; @@ -32,6 +30,12 @@ type EventType = string | symbol; type Listener = (...args: any[]) => any; type EventMap = Record; +let defaultMaxListenersProvider = () => 10; + +export function setDefaultMaxListenersProvider(provider: () => number) { + defaultMaxListenersProvider = provider; +} + export class EventEmitter implements EventEmitterType { private _events: EventMap | undefined = undefined; @@ -58,7 +62,7 @@ export class EventEmitter implements EventEmitterType { } getMaxListeners(): number { - return this._maxListeners === undefined ? OriginalEventEmitter.defaultMaxListeners : this._maxListeners; + return this._maxListeners === undefined ? defaultMaxListenersProvider() : this._maxListeners; } emit(type: EventType, ...args: any[]): boolean { diff --git a/packages/playwright-core/src/client/frame.ts b/packages/playwright-core/src/client/frame.ts index c302da02e4..ecbfe3cb11 100644 --- a/packages/playwright-core/src/client/frame.ts +++ b/packages/playwright-core/src/client/frame.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { EventEmitter } from 'events'; - +import { EventEmitter } from './eventEmitter'; import { ChannelOwner } from './channelOwner'; import { addSourceUrlToScript } from './clientHelper'; import { ElementHandle, convertInputFiles, convertSelectOptionValues } from './elementHandle'; diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index ff992e7ae7..a4f5ff68d0 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { URLSearchParams } from 'url'; - import { ChannelOwner } from './channelOwner'; import { isTargetClosedError } from './errors'; import { Events } from './events'; diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index 43c43ee50c..cb6d0656b8 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -799,7 +799,7 @@ export class Page extends ChannelOwner implements api.Page } async pause(_options?: { __testHookKeepTestTimeout: boolean }) { - if (require('inspector').url()) + if (this._platform.isDebuggerAttached()) return; const defaultNavigationTimeout = this._browserContext._timeoutSettings.defaultNavigationTimeout(); const defaultTimeout = this._browserContext._timeoutSettings.defaultTimeout(); diff --git a/packages/playwright-core/src/common/platform.ts b/packages/playwright-core/src/common/platform.ts index 330b5d6323..10bdc35922 100644 --- a/packages/playwright-core/src/common/platform.ts +++ b/packages/playwright-core/src/common/platform.ts @@ -42,6 +42,7 @@ export type Platform = { createGuid: () => string; fs: () => typeof fs; inspectCustom: symbol | undefined; + isDebuggerAttached(): boolean; isLogEnabled(name: 'api' | 'channel'): boolean; log(name: 'api' | 'channel', message: string | Error | object): void; path: () => typeof path; @@ -70,6 +71,7 @@ export const webPlatform: Platform = { inspectCustom: undefined, + isDebuggerAttached: () => false, isLogEnabled(name: 'api' | 'channel') { return false; @@ -105,6 +107,8 @@ export const emptyPlatform: Platform = { inspectCustom: undefined, + isDebuggerAttached: () => false, + isLogEnabled(name: 'api' | 'channel') { return false; }, diff --git a/packages/playwright-core/src/inProcessFactory.ts b/packages/playwright-core/src/inProcessFactory.ts index 81b40afe19..a53aa8c2e3 100644 --- a/packages/playwright-core/src/inProcessFactory.ts +++ b/packages/playwright-core/src/inProcessFactory.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import path from 'path'; +import * as path from 'path'; +import { EventEmitter } from 'events'; import { AndroidServerLauncherImpl } from './androidServerImpl'; import { BrowserServerLauncherImpl } from './browserServerImpl'; @@ -25,6 +26,7 @@ import { setDebugMode } from './utils/isomorphic/debug'; import { getFromENV } from './server/utils/env'; import { nodePlatform } from './server/utils/nodePlatform'; import { setPlatformForSelectors } from './client/selectors'; +import { setDefaultMaxListenersProvider } from './client/eventEmitter'; import type { Playwright as PlaywrightAPI } from './client/playwright'; import type { Language } from './utils'; @@ -35,6 +37,7 @@ export function createInProcessPlaywright(platform: Platform): PlaywrightAPI { const playwright = createPlaywright({ sdkLanguage: (process.env.PW_LANG_NAME as Language | undefined) || 'javascript' }); setDebugMode(getFromENV('PWDEBUG') || ''); setPlatformForSelectors(nodePlatform); + setDefaultMaxListenersProvider(() => EventEmitter.defaultMaxListeners); setLibraryStackPrefix(path.join(__dirname, '..')); diff --git a/packages/playwright-core/src/server/utils/nodePlatform.ts b/packages/playwright-core/src/server/utils/nodePlatform.ts index 1c2a4dad0c..e9883da361 100644 --- a/packages/playwright-core/src/server/utils/nodePlatform.ts +++ b/packages/playwright-core/src/server/utils/nodePlatform.ts @@ -67,6 +67,8 @@ export const nodePlatform: Platform = { inspectCustom: util.inspect.custom, + isDebuggerAttached: () => !!require('inspector').url(), + isLogEnabled(name: 'api' | 'channel') { return debugLogger.isEnabled(name); },