Skip to content

iter-52: input & eval ergonomics#55

Merged
ractive merged 2 commits intomainfrom
iter-52/input-eval-ergonomics
May 6, 2026
Merged

iter-52: input & eval ergonomics#55
ractive merged 2 commits intomainfrom
iter-52/input-eval-ergonomics

Conversation

@ractive
Copy link
Copy Markdown
Owner

@ractive ractive commented May 6, 2026

Summary

  • type works on React/Vue/Svelte inputs: invoke the native HTMLInputElement / HTMLTextAreaElement / HTMLSelectElement prototype value setter so React's value tracker is invalidated; then dispatch input + change events so framework listeners fire.
  • type --selector S --text T: accept the flag form alongside the positional form. Mixing positional and flag for the same value errors clearly. Unknown flags on type get a tailored hint pointing at both invocation forms.
  • eval IIFE isolation by default: wrap user code in a strict-mode IIFE that runs eval(<source>), so const x = ... no longer collides with a previous call (Firefox's console actor shares global scope otherwise). Single expressions like 1 + 1 still return their value via eval completion semantics.
  • eval --no-isolate: opt out of the IIFE wrap when you want to share scope across calls.

Test plan

  • cargo fmt, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace -q all pass.
  • e2e: type positional and flag forms, --selector/--text conflict, unknown-flag hint.
  • e2e: eval --no-isolate parses; default-isolated eval 'const x = 1; x' succeeds against the mock.
  • Unit: build_script covers the four (isolate × stringify) modes including special-character handling.
  • Manual smoke against real Firefox: type against a React app's controlled input updates bound state; eval 'const x = 1; x' twice in a row succeeds.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added --no-isolate flag to the eval command for disabling default code isolation (IIFE wrapping)
    • Extended the type command to accept --selector and --text flags in addition to positional arguments
    • Improved input compatibility with React, Vue, and Svelte frameworks through enhanced DOM update mechanisms
  • Documentation

    • Enhanced error messages and help text for improved user guidance when using CLI commands

- type: invoke native HTMLInputElement/Textarea/Select prototype value setter
  before assignment so React/Vue/Svelte value trackers see the change; dispatch
  input + change events so framework listeners fire.
- type: accept --selector/--text as named flag synonyms for the positional form.
  Conflicting positional+flag is rejected with a clear AppError. Unknown flags on
  `type` get a tailored hint pointing at both invocation forms.
- eval: wrap user code in a strict-mode IIFE that runs `eval(<source>)` so
  const/let/var declarations stay scoped per call (Firefox's console actor
  otherwise shares scope across evaluations and rejects redeclarations). Single
  expressions still return their value via eval's completion semantics.
- eval: add --no-isolate to opt out and share scope across calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 731000aa-c6fc-4a20-9a8a-125e73ec8286

📥 Commits

Reviewing files that changed from the base of the PR and between f32d3cf and 1e26e2c.

📒 Files selected for processing (8)
  • crates/ff-rdp-cli/src/cli/args.rs
  • crates/ff-rdp-cli/src/commands/eval.rs
  • crates/ff-rdp-cli/src/commands/type_text.rs
  • crates/ff-rdp-cli/src/dispatch.rs
  • crates/ff-rdp-cli/src/main.rs
  • crates/ff-rdp-cli/tests/e2e/eval.rs
  • crates/ff-rdp-cli/tests/e2e/type_text.rs
  • kb/iterations/iteration-52-input-eval-ergonomics.md

📝 Walkthrough

Walkthrough

This pull request extends the CLI API by adding IIFE-based isolation to the eval command with an opt-out flag, supporting dual positional and flag-based input forms for the type command, refactoring type to use native setters for framework compatibility, and introducing contextual error hints when users invoke the type subcommand. End-to-end tests validate all new behaviors, and the iteration is marked complete.

Changes

Input & Eval Ergonomics Enhancement

Layer / File(s) Summary
CLI API Shape
crates/ff-rdp-cli/src/cli/args.rs
Eval variant gains no_isolate: bool field with documentation. Type variant changes from { selector: String, text: String, clear: bool } to { selector_pos: Option<String>, text_pos: Option<String>, selector_flag: Option<String>, text_flag: Option<String>, clear: bool } to support dual-form input. Long help text expanded for both.
Eval Core Implementation
crates/ff-rdp-cli/src/commands/eval.rs
New build_script() function generates final JavaScript, wrapping user code in a strict IIFE by default or passing through if isolation is disabled; handles stringify flag for JSON encoding. Updated run() signature to accept no_isolate parameter, computing an isolate flag and invoking build_script() before evaluation.
Type Core Implementation
crates/ff-rdp-cli/src/commands/type_text.rs
Refactored JavaScript generation to use native prototype setters (HTMLInputElement.prototype.value, etc.) and dispatch input/change events for framework change detection. Introduced JSON encoding of text input and conditional clear-field logic.
Command Dispatch & Validation
crates/ff-rdp-cli/src/dispatch.rs
Eval handler passes no_isolate flag to run(). Type handler validates mutual exclusivity of positional vs. flag-based input forms, extracts concrete selector and text values, and forwards them to the type runner.
Error Hints & CLI Entry
crates/ff-rdp-cli/src/main.rs
Added is_type_invocation() helper to detect when user attempts to invoke the type subcommand despite clap parsing failure. Replaced direct Cli::parse() with try_parse_from() flow, conditionally attaching contextual hint message and exiting with appropriate status codes. Includes test module validating hint detection across argument patterns.
End-to-End Tests & Documentation
crates/ff-rdp-cli/tests/e2e/eval.rs, crates/ff-rdp-cli/tests/e2e/type_text.rs, kb/iterations/iteration-52-input-eval-ergonomics.md
Two new eval tests validate --no-isolate flag acceptance and default IIFE isolation allowing const declarations. Twelve+ new type_text tests cover flag-based invocation, conflict handling, error hints, and native setter marker verification. Knowledge base iteration updated with detailed task completion and acceptance criteria.

Sequence Diagrams

sequenceDiagram
    participant User
    participant CLI as ff-rdp CLI
    participant Eval as eval::run()
    participant Builder as build_script()
    participant JS as JS Evaluator
    
    User->>CLI: eval command with default isolation
    CLI->>Eval: run(..., no_isolate=false)
    Eval->>Builder: build_script(script, isolate=true)
    Builder->>Builder: Wrap in strict IIFE
    Builder-->>Eval: Final script wrapped
    Eval->>JS: evaluate_js_async(final_script)
    JS-->>User: result returned
    
    User->>CLI: eval with --no-isolate flag
    CLI->>Eval: run(..., no_isolate=true)
    Eval->>Builder: build_script(script, isolate=false)
    Builder-->>Eval: Script unchanged
    Eval->>JS: evaluate_js_async(script)
    JS-->>User: result returned
Loading
sequenceDiagram
    participant User
    participant CLI as ff-rdp CLI
    participant Validator as Type Validator
    participant TypeRunner as type_text::run()
    participant JSGen as JS Generator
    participant DOM as Page DOM
    
    User->>CLI: type with flag-based input
    CLI->>Validator: Validate form exclusivity
    Validator-->>CLI: Extract selector and text
    CLI->>TypeRunner: run(selector, text, clear)
    TypeRunner->>JSGen: Generate JS with setter
    JSGen->>JSGen: JSON-encode text
    JSGen-->>TypeRunner: Setter-based JS code
    TypeRunner->>DOM: Evaluate on page
    DOM->>DOM: Call native prototype setter
    DOM->>DOM: Dispatch input and change events
    DOM-->>User: Framework notified of change
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • ractive/ff-rdp#50: Related eval implementation changes; that PR adds stringify flag and wrapping logic while this PR extends with IIFE isolation control via no_isolate flag and build_script abstraction.

Poem

🐰 A hop, a flag, a script wrapped tight,
Eval now nestles in IIFE night,
Type speaks flags with native flair,
Framework hearts now beat aware,
Ergonomics bloom—the CLI takes flight!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch iter-52/input-eval-ergonomics

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves CLI ergonomics and modern framework compatibility by enhancing the type command (React/Vue/Svelte-friendly value setting + better argument UX) and making eval isolated-by-default to avoid Firefox console global-scope redeclaration issues.

Changes:

  • Update type to set values via native element prototype setters and dispatch input/change events for framework-controlled inputs.
  • Allow type --selector/--text flag form alongside positional args, with clear conflict errors and a tailored unknown-flag hint.
  • Wrap eval input in a strict-mode IIFE via eval(<encoded_source>) by default; add eval --no-isolate opt-out and add unit/e2e coverage.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
kb/iterations/iteration-52-input-eval-ergonomics.md Marks iteration 52 tasks/acceptance criteria complete.
crates/ff-rdp-cli/tests/e2e/type_text.rs Adds e2e coverage for type flag-vs-positional behavior and JS payload markers.
crates/ff-rdp-cli/tests/e2e/eval.rs Adds e2e coverage for eval --no-isolate parsing and default isolation acceptance.
crates/ff-rdp-cli/src/main.rs Augments clap parse errors with a type-specific hint using an argv heuristic.
crates/ff-rdp-cli/src/dispatch.rs Implements selector/text resolution logic for type (positional vs flags) and wires eval no_isolate.
crates/ff-rdp-cli/src/commands/type_text.rs Updates JS payload to use native prototype setters + dispatch input/change.
crates/ff-rdp-cli/src/commands/eval.rs Introduces build_script to compose isolation/stringify behavior; adds tests; wires --no-isolate.
crates/ff-rdp-cli/src/cli/args.rs Updates CLI help/docs and adds new flags/positional options for type and eval.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ff-rdp-cli/src/main.rs Outdated
Comment on lines +30 to +35
if a.starts_with("--") {
// Skip global flags that take a value (--host, --port, --timeout, etc.).
// A trailing `=` form is self-contained.
if !a.contains('=') {
let _ = iter.next();
}
Comment on lines +24 to +26
// discarded. We invoke the native prototype setter (cached at
// module-eval time below) to invalidate the tracker, then dispatch the
// synthetic `input`/`change` events the framework listeners expect.
- main.rs: restrict is_type_invocation's lookahead-skip to an allowlist
  of value-taking globals, so booleans like --no-daemon don't swallow
  the `type` token and suppress the tailored hint (Copilot)
- main.rs: drop the dead `let _ = Cli::command();` (and its now-unused
  `CommandFactory` import)
- type_text.rs: fix misleading "cached at module-eval time" comment —
  the prototype setter is looked up on each invocation (Copilot)
- main.rs: add tests covering boolean and mixed-global flag prefixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ractive ractive merged commit fe096c4 into main May 6, 2026
4 of 6 checks passed
@ractive ractive deleted the iter-52/input-eval-ergonomics branch May 6, 2026 20:38
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.

2 participants