Skip to content

fix(browser): prevent const redeclaration in evaluateWithArgs#1834

Open
lw-yang wants to merge 1 commit into
jackwener:mainfrom
lw-yang:fix/evaluate-with-args-redeclaration
Open

fix(browser): prevent const redeclaration in evaluateWithArgs#1834
lw-yang wants to merge 1 commit into
jackwener:mainfrom
lw-yang:fix/evaluate-with-args-redeclaration

Conversation

@lw-yang
Copy link
Copy Markdown
Contributor

@lw-yang lw-yang commented Jun 3, 2026

Summary

  • evaluateWithArgs now wraps its generated const declarations in an IIFE instead of emitting them as bare top-level statements
  • Fixes SyntaxError: Identifier 'markerAttr' has already been declared when multiple browser commands run in sequence on the same page

Problem

Chrome's Runtime.evaluate shares a single global execution context per page. Top-level const declarations persist across calls. When two methods both inject the same variable name via evaluateWithArgs (e.g. markerAttr in tryCdpOnResolvedElement and uploadFile), the second call fails:

SyntaxError: Identifier 'markerAttr' has already been declared

Reproducer: any opencli browser <session> upload <ref> file.png command — it calls click resolution (which injects markerAttr) then upload (which also injects markerAttr).

Fix

Wrap the generated code in an IIFE so const declarations are function-scoped:

// Before (leaks into global context)
return this.evaluate(`${declarations}\n${js}`);

// After (scoped to IIFE)
return this.evaluate(`(() => { ${declarations}\nreturn (${js}); })()`);

Test plan

  • Added 2 unit tests verifying IIFE wrapping and safe repeated-name usage
  • All 41 existing tests pass (vitest run --project unit src/browser/base-page.test.ts)
  • Manually verified: opencli browser <s> upload now works on xiaohongshu creator center (was 100% repro before fix)

🤖 Generated with Claude Code

…lobal const redeclaration

Chrome's Runtime.evaluate shares a single global execution context per page.
Top-level `const` declarations persist across calls, so when the same variable
name is used in multiple evaluateWithArgs invocations (e.g. `markerAttr` in
both click resolution and file upload), the second call throws:
"SyntaxError: Identifier 'markerAttr' has already been declared"

This wraps the generated code in an IIFE so declarations are scoped to a
function body and never leak into the global context.

Reproducer: any command that calls both tryCdpOnResolvedElement() and
uploadFile() in sequence (e.g. `opencli browser <s> upload <ref> file.png`).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant