Repository navigation
[Core] Fix crash from unsynchronized state delete race - #1850
Conversation
webview/js/state.js dispatches the local 'change' CustomEvent *before* sending the pywebviewStateUpdate bridge call to Python. If a duplicate or stale pywebviewStateDelete for the same key ever arrives after the key was already removed on the Python side (e.g. a rapid set/delete race from JavaScript), State.__delattr__ raised AttributeError. js_bridge_call ran the state update/delete branches directly without the try/except used for regular js_api calls, so the exception propagated uncaught into the native bridge callback. On Cocoa/PyObjC this surfaces as an uncaught ObjC exception that kills the whole process instead of just failing one call. Fixes: - webview/util.py: wrap pywebviewStateUpdate/pywebviewStateDelete handling in try/except so a stale or duplicate bridge message logs an error instead of crashing the app. - webview/state.py: use a private _MISSING sentinel instead of None to mark 'key not found' in _delete_state_value, fixing a related bug where deleting a key whose value is legitimately None incorrectly raised AttributeError/KeyError. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
|
@copilot please fix the merge conflicts in this pull request. |
There was a problem hiding this comment.
🟢 Approval recommended
The narrow changes address the reported failures with no blocking issues identified by static review.
No open issues 🎉
What changed in this PR
This PR prevents state synchronization errors from escaping pywebview’s native bridge callbacks and fixes deletion of keys containing None.
Changes:
- Catch state bridge errors and ignore already-missing delete targets.
- Distinguish missing keys from legitimate
Nonevalues using a sentinel. - Document the fixes in the changelog.
| File | Description |
|---|---|
webview/util.py |
Contain exceptions from state bridge operations. |
webview/state.py |
Use a sentinel to identify missing keys during deletion. |
docs/CHANGELOG.md |
Document the state synchronization fixes. |
Review effort: Balanced
Co-authored-by: r0x0r <1549657+r0x0r@users.noreply.github.com>
Resolved in 5835c7b by merging the latest |
Problem
webview/js/state.js's Proxyset/deletetraps dispatch the localchangeCustomEvent before the
pywebviewStateUpdate/pywebviewStateDeletebridgecall reaches Python. If a rapid set/delete race on the same state key ever
produces a stale or duplicate
pywebviewStateDeleteafter the key was alreadyremoved on the Python side,
State.__delattr__/__delitem__raisedAttributeError/KeyError.js_bridge_callhandled the state branches directly with no try/except(unlike the normal
js_apicall path, which already has one), so theexception propagated uncaught into the native bridge callback. On
Cocoa/PyObjC this surfaces as an uncaught ObjC exception (
OC_PythonException)that terminates the whole native process instead of just failing one call.
Fix
webview/util.py: wrap thepywebviewStateUpdate/pywebviewStateDeletehandling in
js_bridge_callin try/except so a stale or duplicate bridgemessage is logged instead of crashing the app.
webview/state.py: use a private_MISSINGsentinel instead ofNonetorepresent "key not found" in
_delete_state_value. This also fixes arelated bug where deleting a key whose value is legitimately
Noneincorrectly raised.
Testing
pytest tests/test_state.py— 20 passedruff check/ruff format --check— cleanCo-authored-by: Copilot 223556219+Copilot@users.noreply.github.com