fix rx.set_clipboard from a backend event handler on Safari/iOS#6595
fix rx.set_clipboard from a backend event handler on Safari/iOS#6595carlosabadia wants to merge 2 commits into
Conversation
Greptile SummaryThis PR fixes
Confidence Score: 4/5The change is well-scoped and correctly handles both WebKit and non-WebKit paths. The one area to watch is the unconditional clipboard-API call on every Safari user gesture. The core logic — arm during gesture, resolve on event, fall back to writeText elsewhere — is correct and well-tested. The only non-trivial concern is that armClipboard fires for every addEvents call on WebKit, issuing navigator.clipboard.write() even when the event batch has nothing to do with the clipboard. Rejected writes leave the clipboard untouched, but some iOS versions may surface a transient clipboard indicator during the pending window, which would be visible on every user interaction on Safari. The armClipboard call site in useEventLoop inside state.js deserves a second look to confirm the arm-every-gesture approach is acceptable across all iOS clipboard UI behaviour. Important Files Changed
Reviews (1): Last reviewed commit: "add new" | Re-trigger Greptile |
| if (isWebKit()) { | ||
| // Arm a clipboard write inside the active user gesture so set_clipboard | ||
| // returned from a backend handler still works on WebKit. No-op unless a | ||
| // user activation is in effect, so programmatic dispatches are unaffected. | ||
| armClipboard(); | ||
| } |
There was a problem hiding this comment.
armClipboard fires on every user gesture on WebKit, not just clipboard ones
addEvents calls armClipboard() unconditionally for every event on Safari/iOS (guarded only by isWebKit()). Any user interaction — typing in a form field, navigating, clicking unrelated buttons — that has an active userActivation will trigger navigator.clipboard.write() with a pending promise. When no _set_clipboard event follows, that write is rejected and .catch(() => {}) silently swallows it, so the clipboard is never modified. However, some WebKit/iOS versions surface a transient clipboard-access indicator even for in-flight writes that ultimately fail, which could be disorienting to users clicking unrelated elements. Consider checking whether the outgoing event batch actually contains or is likely to produce a _set_clipboard response before arming — or document that the arm-for-every-gesture trade-off was explicitly evaluated against iOS clipboard UI behaviour.
masenf
left a comment
There was a problem hiding this comment.
i'm quite hesitant on this one, because i don't like the idea of entering that clipboard.write promise for every event on a webkit browser.
is it possible to refactor the places where we're returning set_clipboard from the backend to just not do that. we can say set_clipboard has to be directly attached to an event trigger and maybe even raise an error/warning if someone tries to use it from the backend?
the other option i was considering, but @adhami3310 didn't really like, is exposing this clipboard arming behavior as an event action (like debounce or throttle). then backend events that wanted clipboard permissions could set this as a kwarg on the rx.event decorator or pass it at the trigger site to opt-in to the clipboard arming. this kind of falls apart for chained events on the backend though because the clipboard opt-in event stuff would only work if that event handler is directly attached to a component's trigger.
i still think just warning when set_clipboard is used from the backend and maybe updating the docs to show examples of directly attaching it to a trigger is the simplest solution so we don't have to maintain hacks or try to break safari's security model for questionable gains.
closes #6583