Skip to content

fix(sdk-ts): preserve JSON keys in script arguments - #3361

Draft
yunyv wants to merge 4 commits into
browserbase:mainfrom
yunyv:fix/script-json-arguments
Draft

yunyv wants to merge 4 commits into
browserbase:mainfrom
yunyv:fix/script-json-arguments

Conversation

@yunyv

@yunyv yunyv commented Oct 31, 2026 •

Copy link
Copy Markdown

why

Function arguments for page.evaluate(), page.addInitScript(), and context.addInitScript() are validated as JSON but currently embedded in the generated source as an object literal. An own __proto__ JSON key then receives JavaScript object-literal semantics instead of remaining data. For example, a parsed JSON object containing that key loses it when the callback serializes its argument again; nested keys are affected too.

This was found by inspection and reproduced against the actual SDK modules, rather than a production browser session.

what changed

  • Reuse the existing parsedArgument helper, already used by waitForFunction, for the two function-argument normalization paths. It reconstructs JSON data with JSON.parse and preserves omitted arguments as undefined.
  • Add regression coverage for own keys, nested arrays/objects, primitives, omitted arguments, and escaped/Unicode strings. Raw script strings and validation of non-JSON values stay unchanged.
  • Update three wrapper expectations for the generated source and add a patch Changeset for the TypeScript SDK only. No protocol or extension changes.

test plan

  • New own-key regressions against unchanged main: 3 failed, 6 passed in the initial nine-case suite; patched 9 passed. The final suite adds ordinary JSON/escaping coverage.
  • Final SDK unit tests: 628 passed across 27 files, excluding browser-runtime/integration and the package contract. Two focused test files: 104 passed.
  • Independent review: 10 failed, 16 passed on baseline; 26 passed after the fix. It exercises the actual generated source with node:vm, including nested keys, prototype identity, escaping, omitted arguments and validation errors.
  • A separate diagnostic calls the real public Page/BrowserContext methods with only the transport replaced by a test seam, then executes their emitted source. Baseline fails; all three patched paths pass. This is not a real-browser E2E test.
  • SDK TypeScript checking, scoped Oxlint/Oxfmt, Changeset validation and its seven utility tests, and git diff --check pass.
  • The extension production build passes. SDK production tsdown was killed with exit 137; a resource-limited retry exhausted its JavaScript heap (exit 134). The package contract therefore still fails because the SDK distribution was not built. The full attempted SDK unit run was 628 passed, 1 failed; that failed package check is not counted as passing.

Node 24.22.1, pinned workspace dependencies. Full monorepo checks, Python/Go suites, real-browser tests and live provider tests were not run.

AI assistance was used for implementation and testing, with a separate automated review. No human review is claimed.


Summary by cubic

Fixes function arguments passed to page.evaluate(), page.addInitScript(), and context.addInitScript() losing own __proto__ JSON keys. Arguments are now embedded via JSON.parse(...) instead of as object literals, so serialized JSON keeps its keys exactly.

  • Adds regression tests for own keys, nested values, primitives, omitted arguments, and escaped/Unicode strings.
  • Adds a patch Changeset for the TypeScript SDK.

Written for commit 77f0f72. Summary will update on new commits.

View guided diff

@changeset-bot

changeset-bot Bot commented Oct 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 77f0f72

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@browserbasehq/stagehand Patch
browse Patch
@browserbasehq/stagehand-examples Patch
@browserbasehq/stagehand-integrations-claude-cua-sdk Patch
@browserbasehq/stagehand-integrations Patch
@browserbasehq/eve Patch
@browserbasehq/stagehand-integrations-gemini-cua-sdk Patch
@browserbasehq/stagehand-integrations-example-pi-facade Patch
@browserbasehq/stagehand-integrations-claude-agent-sdk Patch
@browserbasehq/stagehand-integrations-example-claude-code-facade Patch
@browserbasehq/stagehand-integrations-codex-sdk Patch
@browserbasehq/stagehand-integrations-example-codex-facade Patch
@browserbasehq/stagehand-integrations-cursor-sdk Patch
@browserbasehq/stagehand-integrations-example-cursor-facade Patch
@browserbasehq/stagehand-integrations-deepagents-sdk Patch
@browserbasehq/stagehand-integrations-eve-sdk Patch
@browserbasehq/stagehand-integrations-fx-sdk Patch
@browserbasehq/stagehand-integrations-mastra-sdk Patch
@browserbasehq/stagehand-integrations-example-mastra-facade Patch
@browserbasehq/stagehand-integrations-pi-sdk Patch
@browserbasehq/stagehand-integrations-example-vercel-ai-facade Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run.
Approving the latest commit mirrors it into an internal PR owned by the approver.
If new commits are pushed later, the internal PR stays open but is marked stale until someone approves the latest external commit and refreshes it.

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. labels Oct 31, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant