mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-18 15:50:11 +02:00
fix(browse): make --gstack-suppress-prepare-stack-trace opt-in, not default-on
buildGStackLaunchArgs() pushed the flag unless GSTACK_CDP_STEALTH=off, i.e.
on-by-default — contradicting its own comment ("off by default, only for
gbrowser builds"). The switch is read by a C++ patch that only exists in
gbrowser; on stock Playwright Chromium it is an unknown switch.
Flip to opt-in: emit only when GSTACK_CDP_STEALTH is on/1/true. gbd opts in by
exporting GSTACK_CDP_STEALTH=on; stock installs leave it unset so the flag
never reaches a Chromium that wouldn't understand it. Comment now matches code.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-6
@@ -515,12 +515,18 @@ export function buildGStackLaunchArgs(): string[] {
|
||||
if (memory) args.push(`--gstack-device-memory=${memory}`);
|
||||
|
||||
// Pack 2 / B11: suppress user-defined Error.prepareStackTrace during
|
||||
// V8 stack-trace formatting. Closes the Cloudflare Bot Management
|
||||
// canary trick where a page sets prepareStackTrace and watches for
|
||||
// it to fire during CDP serialization. Off by default — only set
|
||||
// when the C++ patch is present (gbrowser builds), gstack hosts
|
||||
// running stock Playwright Chromium leave it unset.
|
||||
if (env.GSTACK_CDP_STEALTH !== 'off') {
|
||||
// V8 stack-trace formatting. Closes the Cloudflare Bot Management canary
|
||||
// trick where a page sets prepareStackTrace and watches for it to fire
|
||||
// during CDP serialization.
|
||||
//
|
||||
// OPT-IN (off by default): only emitted when GSTACK_CDP_STEALTH is
|
||||
// on/1/true. This switch is read by a C++ patch that only exists in
|
||||
// gbrowser builds; gbd opts in by exporting GSTACK_CDP_STEALTH=on. Stock
|
||||
// Playwright Chromium leaves it unset, so the flag never reaches a
|
||||
// Chromium that wouldn't understand it. (Previously this was on-by-default
|
||||
// unless GSTACK_CDP_STEALTH=off, which contradicted this very comment.)
|
||||
const cdpStealth = env.GSTACK_CDP_STEALTH;
|
||||
if (cdpStealth === 'on' || cdpStealth === '1' || cdpStealth === 'true') {
|
||||
args.push('--gstack-suppress-prepare-stack-trace');
|
||||
}
|
||||
|
||||
|
||||
@@ -142,18 +142,16 @@ describe('buildGStackLaunchArgs — Pack 1 cmdline-switch construction', () => {
|
||||
}
|
||||
}
|
||||
|
||||
test('empty env produces only the always-on prepare-stack-trace flag', () => {
|
||||
test('empty env produces no switches (suppress-stack is opt-in)', () => {
|
||||
withEnv({}, () => {
|
||||
// The Pack 2 / B11 suppression flag is always emitted unless
|
||||
// explicitly disabled via GSTACK_CDP_STEALTH=off. Six per-install
|
||||
// flags fall through (nothing in env), so we expect just one.
|
||||
expect(buildGStackLaunchArgs()).toEqual([
|
||||
'--gstack-suppress-prepare-stack-trace',
|
||||
]);
|
||||
// All switches are opt-in: the six per-install flags fall through
|
||||
// (nothing in env), and the Pack 2 / B11 suppression flag is only
|
||||
// emitted when GSTACK_CDP_STEALTH is on/1/true. Empty env → [].
|
||||
expect(buildGStackLaunchArgs()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
test('all env values populated → all 7 switches emitted', () => {
|
||||
test('all env values populated (incl. CDP stealth opt-in) → all 7 switches emitted', () => {
|
||||
withEnv({
|
||||
GSTACK_GPU_VENDOR: 'Apple Inc.',
|
||||
GSTACK_GPU_RENDERER: 'ANGLE (Apple, ANGLE Metal Renderer: Apple M4 Max, Unspecified Version)',
|
||||
@@ -161,6 +159,7 @@ describe('buildGStackLaunchArgs — Pack 1 cmdline-switch construction', () => {
|
||||
GSTACK_GPU_CHIPSET: 'Apple M4 Max',
|
||||
GSTACK_HW_CONCURRENCY: '16',
|
||||
GSTACK_DEVICE_MEMORY: '8',
|
||||
GSTACK_CDP_STEALTH: 'on',
|
||||
}, () => {
|
||||
const args = buildGStackLaunchArgs();
|
||||
expect(args).toContain('--gstack-gpu-vendor=Apple Inc.');
|
||||
@@ -195,17 +194,26 @@ describe('buildGStackLaunchArgs — Pack 1 cmdline-switch construction', () => {
|
||||
test('partial env: only set switches that have values', () => {
|
||||
withEnv({ GSTACK_HW_CONCURRENCY: '12' }, () => {
|
||||
const args = buildGStackLaunchArgs();
|
||||
// expect hw + the always-on prepare-stack-trace suppression
|
||||
// hw only — suppress-stack is opt-in and GSTACK_CDP_STEALTH is unset.
|
||||
expect(args).toContain('--gstack-hw-concurrency=12');
|
||||
expect(args).toContain('--gstack-suppress-prepare-stack-trace');
|
||||
expect(args.length).toBe(2);
|
||||
expect(args).not.toContain('--gstack-suppress-prepare-stack-trace');
|
||||
expect(args.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
test('GSTACK_CDP_STEALTH=off disables prepare-stack-trace suppression', () => {
|
||||
test('prepare-stack-trace suppression is opt-in via GSTACK_CDP_STEALTH', () => {
|
||||
// on/1/true enable it; off and unset omit it, so stock Playwright
|
||||
// Chromium (no GSTACK_CDP_STEALTH) never receives the unknown switch.
|
||||
for (const v of ['on', '1', 'true']) {
|
||||
withEnv({ GSTACK_CDP_STEALTH: v }, () => {
|
||||
expect(buildGStackLaunchArgs()).toContain('--gstack-suppress-prepare-stack-trace');
|
||||
});
|
||||
}
|
||||
withEnv({ GSTACK_CDP_STEALTH: 'off' }, () => {
|
||||
const args = buildGStackLaunchArgs();
|
||||
expect(args).not.toContain('--gstack-suppress-prepare-stack-trace');
|
||||
expect(buildGStackLaunchArgs()).not.toContain('--gstack-suppress-prepare-stack-trace');
|
||||
});
|
||||
withEnv({}, () => {
|
||||
expect(buildGStackLaunchArgs()).not.toContain('--gstack-suppress-prepare-stack-trace');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user