diff options
| -rw-r--r-- | pearl.el | 32 | ||||
| -rw-r--r-- | tests/test-pearl-bugfixes.el | 25 |
2 files changed, 45 insertions, 12 deletions
@@ -2418,13 +2418,18 @@ proceeds and the subtree is replaced with Linear's version." (message "Issue %s is no longer on Linear (deleted or no access); not refreshing" issue-id)) (raw - (save-excursion - (goto-char marker) - (pearl--replace-issue-subtree-at-point - (pearl--normalize-issue raw))) - (pearl-highlight-comments) - (pearl--surface-buffer (marker-buffer marker)) - (message "Refreshed %s from Linear" issue-id))))))))) + ;; The fetch may complete after the buffer was killed; only + ;; rewrite it when it's still live. + (if (buffer-live-p (marker-buffer marker)) + (progn + (save-excursion + (goto-char marker) + (pearl--replace-issue-subtree-at-point + (pearl--normalize-issue raw))) + (pearl-highlight-comments) + (pearl--surface-buffer (marker-buffer marker)) + (message "Refreshed %s from Linear" issue-id)) + (message "Refreshed %s; its buffer was closed" issue-id)))))))))) (defun pearl--create-comment-async (issue-id body callback) "Create a comment with BODY on ISSUE-ID via commentCreate. @@ -2657,12 +2662,15 @@ tail of the field-setter commands (priority/state/assignee/labels)." issue-id fields (lambda (result) (if (plist-get result :success) + ;; The push may complete after the buffer was killed; only touch it + ;; when it's still live, but still report the (remote) success. (progn - (save-excursion - (goto-char marker) - (funcall on-success)) - (message "%s" success-message) - (pearl--surface-buffer (marker-buffer marker))) + (when (buffer-live-p (marker-buffer marker)) + (save-excursion + (goto-char marker) + (funcall on-success)) + (pearl--surface-buffer (marker-buffer marker))) + (message "%s" success-message)) (message "%s" fail-message))))) (defun pearl-set-priority (priority-name) diff --git a/tests/test-pearl-bugfixes.el b/tests/test-pearl-bugfixes.el index 7f5c635..caab884 100644 --- a/tests/test-pearl-bugfixes.el +++ b/tests/test-pearl-bugfixes.el @@ -151,5 +151,30 @@ (should-error (pearl-run-saved-query "bad") :type 'user-error) (should-not fetched)))) +;;; Bug: async issue callbacks must be harmless if the buffer is killed + +(ert-deftest test-pearl-push-issue-field-killed-buffer-no-signal () + "A field push whose buffer is killed before the success callback does not signal." + (let ((buf (generate-new-buffer "pearl-pif-kill"))) + (unwind-protect + (let (marker) + (with-current-buffer buf + (insert "* h\n:PROPERTIES:\n:LINEAR-ID: a\n:END:\nbody\n") + (org-mode) + (goto-char (point-min)) + (setq marker (point-marker))) + ;; The update stub kills the buffer, then reports success; the success + ;; callback must not run its buffer ops (or signal) on a dead buffer. + (cl-letf (((symbol-function 'pearl--update-issue-async) + (lambda (_id _fields cb) (kill-buffer buf) (funcall cb '(:success t))))) + ;; Must complete without signaling; the on-success thunk (which would + ;; error) must not run because the buffer is dead. + (pearl--push-issue-field + "a" marker '(("priority" . 2)) + (lambda () (error "on-success must not run against a dead buffer")) + "ok" "fail") + (should-not (buffer-live-p buf)))) + (when (buffer-live-p buf) (kill-buffer buf))))) + (provide 'test-pearl-bugfixes) ;;; test-pearl-bugfixes.el ends here |
