Skip to content

Commit a3919e8

Browse files
--wip-- [skip ci]
1 parent 260ad3c commit a3919e8

2 files changed

Lines changed: 75 additions & 13 deletions

File tree

packages/core/binding.gyp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@
1616
"-Wno-unused-but-set-variable",
1717
"-Wno-type-limits",
1818
"-Wno-format",
19-
"-Wno-format-security"
19+
"-Wno-format-security",
20+
"-Wno-error=format-security"
2021
],
22+
"xcode_settings": {
23+
"OTHER_CFLAGS": [
24+
"-Wno-format",
25+
"-Wno-format-security",
26+
"-Wno-error=format-security"
27+
]
28+
},
2129
"cflags_cc": [
2230
"-Wno-maybe-uninitialized",
2331
"-Wno-unused-variable",

packages/playwright/src/index.ts

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
type Benchmark,
1010
type BenchmarkStats,
1111
} from "@codspeed/core";
12+
import { createRequire } from "node:module";
13+
import { pathToFileURL } from "node:url";
1214
import { _electron as electron } from "playwright";
1315
import type { ElectronApplication, Page } from "playwright-core";
1416

@@ -32,6 +34,11 @@ export interface BenchFixtures {
3234
*/
3335
export type BenchFunction = (fixtures: BenchFixtures) => void | Promise<void>;
3436

37+
/**
38+
* A hook run around the measured region. Not included in the reported timing.
39+
*/
40+
export type BenchHook = (fixtures: BenchFixtures) => void | Promise<void>;
41+
3542
/**
3643
* Minimal options for a benchmark. Inspired by Vitest's `bench`, but kept
3744
* deliberately small.
@@ -47,20 +54,45 @@ export interface BenchOptions {
4754
*/
4855
appPath: string;
4956
/**
50-
* Additional CLI flags forwarded to Electron.
57+
* CLI flags forwarded to Electron.
5158
*/
5259
electronArgs?: string[];
5360
/**
5461
* Working directory for the Electron process. Defaults to `process.cwd()`.
5562
*/
5663
cwd?: string;
5764
/**
58-
* Absolute path to the Electron executable. When omitted, Playwright resolves
59-
* it via `require("electron")`. Set this when running under package managers
60-
* (e.g. pnpm) where Playwright cannot resolve `electron` from its own
61-
* directory.
65+
* Absolute path to the Electron executable. When omitted, it is resolved from
66+
* the `electron` package in `cwd`. Set this only to override that default.
67+
*/
68+
electronExecutablePath?: string;
69+
/**
70+
* Run before each round, after the window opens. Use it to bring the app to
71+
* a steady state (initial render done, data loaded, …). Not measured.
72+
*/
73+
setup?: BenchHook;
74+
/**
75+
* Run after each round, before the app is closed. Use it for teardown that
76+
* should not be measured.
6277
*/
63-
executablePath?: string;
78+
teardown?: BenchHook;
79+
}
80+
81+
let integrationInitialized = false;
82+
83+
/**
84+
* Register the integration and environment with the instrumentation. This is
85+
* process-global, so it only needs to run once regardless of how many
86+
* benchmarks are defined.
87+
*/
88+
function ensureIntegrationSetup(): void {
89+
if (integrationInitialized) return;
90+
integrationInitialized = true;
91+
92+
InstrumentHooks.setIntegration("node-custom", __VERSION__);
93+
InstrumentHooks.setEnvironment("nodejs", "version", process.versions.node);
94+
InstrumentHooks.setEnvironment("nodejs", "v8", process.versions.v8);
95+
InstrumentHooks.writeEnvironment(process.pid);
6496
}
6597

6698
function resolveRounds(optionRounds: number | undefined): number {
@@ -74,15 +106,32 @@ function resolveRounds(optionRounds: number | undefined): number {
74106
return n;
75107
}
76108

109+
/**
110+
* Resolve the path to the Electron binary.
111+
*
112+
* Playwright resolves Electron via `require("electron/index.js")` from inside
113+
* its own package directory. Under isolated installs (e.g. pnpm), Playwright
114+
* cannot see the project's `electron` dependency and bails out with
115+
* "Electron executablePath not found!". We resolve it ourselves from the
116+
* benchmark's working directory, where `electron` is a real dependency.
117+
*/
118+
function resolveElectronExecutable(cwd: string): string {
119+
const require = createRequire(pathToFileURL(`${cwd}/`));
120+
// `electron`'s main module exports the absolute path to its binary.
121+
return require("electron") as string;
122+
}
123+
77124
async function launchApp(options: BenchOptions): Promise<ElectronApplication> {
125+
const cwd = options.cwd ?? process.cwd();
78126
return electron.launch({
79127
args: [
80128
options.appPath,
81129
...(options.electronArgs ?? []),
82130
`--js-flags=${DEFAULT_PROFILING_JS_FLAGS}`,
83131
],
84-
cwd: options.cwd ?? process.cwd(),
85-
executablePath: options.executablePath,
132+
cwd,
133+
executablePath:
134+
options.electronExecutablePath ?? resolveElectronExecutable(cwd),
86135
});
87136
}
88137

@@ -94,6 +143,10 @@ async function runOneSample(
94143
const page = await app.firstWindow();
95144

96145
try {
146+
if (options.setup) {
147+
await options.setup({ page });
148+
}
149+
97150
const startTs = InstrumentHooks.currentTimestamp();
98151
await fn({ page });
99152
const endTs = InstrumentHooks.currentTimestamp();
@@ -105,6 +158,10 @@ async function runOneSample(
105158
);
106159
InstrumentHooks.addMarker(process.pid, MARKER_TYPE_BENCHMARK_END, endTs);
107160

161+
if (options.teardown) {
162+
await options.teardown({ page });
163+
}
164+
108165
return endTs - startTs;
109166
} finally {
110167
await app.close();
@@ -177,10 +234,7 @@ export async function bench(
177234
const rounds = resolveRounds(options.rounds);
178235
const uri = `${getCallingFile(0)}::${name}`;
179236

180-
InstrumentHooks.setIntegration("node-custom", __VERSION__);
181-
InstrumentHooks.setEnvironment("nodejs", "version", process.versions.node);
182-
InstrumentHooks.setEnvironment("nodejs", "v8", process.versions.v8);
183-
InstrumentHooks.writeEnvironment(process.pid);
237+
ensureIntegrationSetup();
184238

185239
InstrumentHooks.setExecutedBenchmark(process.pid, uri);
186240
InstrumentHooks.startBenchmark();

0 commit comments

Comments
 (0)