feat(terminal): add runtime renderer switch

This commit is contained in:
zhangheng
2026-06-24 15:31:58 +08:00
parent 7ee8d7bde1
commit 1334685fac
5 changed files with 171 additions and 7 deletions

View File

@@ -24,6 +24,7 @@ export function parseArgs(argv) {
screenshot: true,
browserChannel: process.env.PLAYWRIGHT_BROWSER_CHANNEL || "",
browserExecutable: process.env.PLAYWRIGHT_BROWSER_EXECUTABLE || "",
renderer: "webgl",
};
for (let index = 0; index < argv.length; index += 1) {
@@ -50,6 +51,8 @@ export function parseArgs(argv) {
options.browserChannel = next();
} else if (arg === "--browser-executable") {
options.browserExecutable = next();
} else if (arg === "--renderer") {
options.renderer = parseRenderer(next());
} else if (arg === "--no-screenshot") {
options.screenshot = false;
} else if (arg === "--help" || arg === "-h") {
@@ -173,11 +176,18 @@ async function runScenario(browser, options, viewport) {
const page = await context.newPage();
const frameSamples = [];
try {
await page.goto(options.url, { waitUntil: "networkidle", timeout: options.timeoutMs });
await page.waitForSelector(".terminal-screen", { timeout: options.timeoutMs });
await page.waitForSelector("canvas.terminal-canvas:not([hidden])", {
await page.goto(benchUrl(options), {
waitUntil: "networkidle",
timeout: options.timeoutMs,
});
await page.waitForSelector(".terminal-screen", { timeout: options.timeoutMs });
if (options.renderer === "dom") {
await page.waitForSelector(".terminal-row", { timeout: options.timeoutMs });
} else {
await page.waitForSelector("canvas.terminal-canvas:not([hidden])", {
timeout: options.timeoutMs,
});
}
await page.evaluate(() => {
window.__terminalBenchFrames = [];
@@ -236,7 +246,10 @@ async function runScenario(browser, options, viewport) {
const screenshot = await page.screenshot({ fullPage: false });
const screenshotSmoke = pngSmokeFromBuffer(screenshot);
if (options.screenshot) {
screenshotPath = path.join(options.outputDir, `terminal-${viewport.name}.png`);
screenshotPath = path.join(
options.outputDir,
`terminal-${options.renderer}-${viewport.name}.png`,
);
fs.writeFileSync(screenshotPath, screenshot);
}
@@ -256,6 +269,7 @@ async function runScenario(browser, options, viewport) {
return {
viewport,
requestedRenderer: options.renderer,
lines: options.lines,
elapsedMs,
rowsPerSecond: round(options.lines / (elapsedMs / 1000)),
@@ -269,6 +283,12 @@ async function runScenario(browser, options, viewport) {
}
}
function benchUrl(options) {
const url = new URL(options.url);
url.searchParams.set("renderer", options.renderer);
return url.toString();
}
function browserLaunchOptions(options) {
if (options.browserChannel) {
return { channel: options.browserChannel };
@@ -393,6 +413,14 @@ function positiveInt(value, label) {
return parsed;
}
function parseRenderer(value) {
const normalized = value.toLowerCase();
if (["webgl", "canvas", "dom"].includes(normalized)) {
return normalized;
}
throw new Error(`--renderer must be one of: webgl, canvas, dom`);
}
function round(value) {
return Math.round(value * 100) / 100;
}
@@ -409,6 +437,7 @@ Options:
--lines <n> Default: ${DEFAULT_LINES}
--viewport <cols>x<rows> Run one scenario with inferred browser size
--viewport <c>x<r>:<w>x<h> Run one scenario with explicit browser size
--renderer <name> webgl, canvas, or dom. Default: webgl
--browser-channel <name> Use an installed browser channel, e.g. chrome
--browser-executable <path> Use a local Chromium/Chrome executable path
--timeout-ms <n> Default: 120000