fix: Windows support — Node.js server fallback for Playwright (#255)

* fix: Windows support — Node.js server fallback for Playwright

Setup hangs on Windows 11 because Bun's child_process can't handle
Playwright's --remote-debugging-pipe (fd 3/4 pipe handles). Fall back
to Node.js on Windows for both the setup verification and server
runtime. macOS/Linux completely unaffected — all Windows code behind
IS_WINDOWS / process.platform === 'win32' guards.

Based on community PR #194 by @sozairali. Fixed sed -i portability
(perl -pi -e) in build-node-server.sh for macOS compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: cross-platform path handling for Windows compatibility

Replace hardcoded '/tmp' and 'dir + "/"' path checks with
platform-aware constants from new platform.ts module. On macOS/Linux
this evaluates identically ('/tmp', '/'); on Windows it uses
os.tmpdir() and path.sep. Zero behavior change on Unix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add tests for Windows polyfill, platform constants, and Node server resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: Windows support in README + CHANGELOG (v0.9.1.1)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.9.3.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-03-20 12:22:11 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 6a6b2b0766
commit d7c732b282
20 changed files with 430 additions and 29 deletions
+3 -2
View File
@@ -10,6 +10,7 @@ import { consoleBuffer, networkBuffer, dialogBuffer } from './buffers';
import type { Page } from 'playwright';
import * as fs from 'fs';
import * as path from 'path';
import { TEMP_DIR, isPathWithin } from './platform';
/** Detect await keyword, ignoring comments. Accepted risk: await in string literals triggers wrapping (harmless). */
function hasAwait(code: string): boolean {
@@ -36,12 +37,12 @@ function wrapForEvaluate(code: string): string {
}
// Security: Path validation to prevent path traversal attacks
const SAFE_DIRECTORIES = ['/tmp', process.cwd()];
const SAFE_DIRECTORIES = [TEMP_DIR, process.cwd()];
export function validateReadPath(filePath: string): void {
if (path.isAbsolute(filePath)) {
const resolved = path.resolve(filePath);
const isSafe = SAFE_DIRECTORIES.some(dir => resolved === dir || resolved.startsWith(dir + '/'));
const isSafe = SAFE_DIRECTORIES.some(dir => isPathWithin(resolved, dir));
if (!isSafe) {
throw new Error(`Absolute path must be within: ${SAFE_DIRECTORIES.join(', ')}`);
}