Skip to content

fix: Always invalidate server-side input values for incoming wire messages#2220

Merged
schloerke merged 8 commits intomainfrom
schloerke/input-dedupe-test
Apr 17, 2026
Merged

fix: Always invalidate server-side input values for incoming wire messages#2220
schloerke merged 8 commits intomainfrom
schloerke/input-dedupe-test

Conversation

@schloerke
Copy link
Copy Markdown
Collaborator

@schloerke schloerke commented Apr 17, 2026

Summary

  • Clear Value._value to MISSING before calling _set() in _manage_inputs so the server always accepts incoming Input values as new values
  • The client sends values in two cases: genuinely new values, or {priority: "event"} which bypasses client-side dedup (InputNoResendDecorator). Either way, the server should invalidate dependents.
  • Previously, Value._set() used identity (is) which silently dropped updates for CPython-interned objects (small ints, short strings), breaking priority: "event" behavior

Resolves #2219
Resolves #1600

Test plan

  • New Playwright test with 4 buttons testing all combinations of value type (integer vs list) and priority (default vs event)
  • Unit tests pass (751 passed, 0 failed)
  • Playwright test passes

🤖 Generated with Claude Code

schloerke and others added 4 commits April 17, 2026 15:40
…sages

The client sends a value over the wire in two cases: either it's a
genuinely new value, or it was sent with {priority: "event"} which
bypasses client-side deduplication (InputNoResendDecorator). Either way,
the server should accept this value as new and cause dependents to
recalculate.

Previously, Value._set() used an identity check (self._value is value)
that silently dropped updates for CPython-interned objects like small
integers. This meant Shiny.setInputValue("x", 42, {priority: "event"})
would only fire the reactive effect once, even though R Shiny fires it
every time.

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

Tests that sending interned strings like "" and "x=1" with
{priority: "event"} correctly fires the reactive effect every time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Not browser-specific behavior, no need to run on all browsers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@schloerke schloerke force-pushed the schloerke/input-dedupe-test branch from 84d7798 to cacdb9c Compare April 17, 2026 19:47
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

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 fixes server-side deduplication of incoming input values so that Shiny.setInputValue(..., {priority: "event"}) reliably triggers reactive invalidation on every send (including CPython-interned values like small ints and empty strings), aligning behavior with R Shiny’s dedupe = FALSE.

Changes:

  • Updated session input handling to force incoming wire messages to be treated as “new” values (always invalidating dependents).
  • Added a new Playwright regression app + tests covering integer/list values under default vs event priority, plus a dedicated string regression for #1600.
  • Added a changelog entry describing the fix.

Reviewed changes

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

File Description
shiny/session/_session.py Adjusts server-side input update logic so incoming client values always trigger reactive invalidation.
tests/playwright/shiny/inputs/input_setinputvalue_dedupe/app.py Adds a minimal Shiny app used to exercise setInputValue dedupe vs event semantics.
tests/playwright/shiny/inputs/input_setinputvalue_dedupe/test_input_setinputvalue_dedupe.py Adds Playwright coverage for the regression scenarios (ints/lists/strings; default vs event).
CHANGELOG.md Documents the bug fix for server-side input deduplication.

Comment thread shiny/session/_session.py Outdated
schloerke and others added 3 commits April 17, 2026 16:05
Add `force=False` keyword arg to `_set()` that skips the identity
short-circuit. This avoids fabricating a MISSING transition that would
spuriously invalidate is_set() dependents on every input message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Confirms that force-setting the same value re-fires value dependents
but does not spuriously invalidate is_set() dependents.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Click both buttons per iteration so the event-priority assertion acts
as a synchronization point, proving the default-priority click has been
processed before asserting its count stayed at 1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@schloerke schloerke merged commit b3ba490 into main Apr 17, 2026
171 of 172 checks passed
@schloerke schloerke deleted the schloerke/input-dedupe-test branch April 17, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants