branch: externals/org commit 4b546e04af85e757902b57963854a35690739514 Author: Ihor Radchenko <yanta...@posteo.net> Commit: Ihor Radchenko <yanta...@posteo.net>
org-element--cache-submit-request: Ensure correct cache synchronization * lisp/org-element.el (org-element--cache-sync): Add new optional argument FORCE to force cache synchronization even when `org-element--cache-active-p' returns non-nil. Update commentary explaining why `org-element--cache-active-p' needs to be checked. (org-element--cache-submit-request): Force cache synchronization. We are safe to force it as all the callers of `org-element--cache-submit-request' do check that cache is active. This fixes an edge case when Org buffer has transient indirect buffers with `after-change-functions' not being setup. If a change happens in the main Org buffer, `org-element--cache-after-change' gets called and cache request is processed even though (org-element--cache-active-p), but not (org-element--cache-active-p t), returns nil (due to the indirect buffer). Before this commit, `org-element--cache-submit-request' called by `org-element--cache-after-change' missed cache synchronization, as `org-element--cache-sync' did nothing. As a result, if the indirect buffer would get deleted, we would end up with incorrect cache state. Reported-by: Gregor Zattler <telegr...@gmx.net> --- lisp/org-element.el | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index b9e93f60e1..a3d9092909 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -5985,7 +5985,7 @@ It is a symbol among nil, t, or a number representing smallest level of modified headline. The level considers headline levels both before and after the modification.") -(defun org-element--cache-sync (buffer &optional threshold future-change offset) +(defun org-element--cache-sync (buffer &optional threshold future-change offset force) "Synchronize cache with recent modification in BUFFER. When optional argument THRESHOLD is non-nil, do the @@ -5998,13 +5998,18 @@ FUTURE-CHANGE, when non-nil, is a buffer position where changes not registered yet in the cache are going to happen. OFFSET is the change offset. It is used in `org-element--cache-submit-request', where cache is partially updated before current modification are -actually submitted." +actually submitted. + +FORCE, when non-nil will force the synchronization even when +`org-element--cache-active-p' returns nil." (when (buffer-live-p buffer) (org-with-base-buffer buffer ;; Do not sync when, for example, in the middle of ;; `combine-change-calls'. See the commentary inside - ;; `org-element--cache-active-p'. - (when (and org-element--cache-sync-requests (org-element--cache-active-p)) + ;; `org-element--cache-active-p'. Such situation may occur when + ;; sync timer triggers in the middle of `combine-change-calls'. + (when (and org-element--cache-sync-requests + (or force (org-element--cache-active-p))) ;; Check if the buffer have been changed outside visibility of ;; `org-element--cache-before-change' and `org-element--cache-after-change'. (if (/= org-element--cache-last-buffer-size (buffer-size)) @@ -7072,7 +7077,7 @@ change, as an integer." ;; yet to the otherwise correct part of the cache (i.e, before ;; the first request). (org-element--cache-log-message "Adding new phase 0 request") - (when next (org-element--cache-sync (current-buffer) end beg offset)) + (when next (org-element--cache-sync (current-buffer) end beg offset 'force)) (let ((first (org-element--cache-for-removal beg end offset))) (if first (push (let ((first-beg (org-element-property :begin first))