patches: 0008 fix current_buffer bug + unbind_to on all return paths

Fbuffer_substring_no_properties operates on current_buffer, not the
passed buffer. Added set_buffer_internal_1 + record_unwind_current_buffer
with unbind_to on every return path.
This commit is contained in:
2026-02-28 16:15:41 +01:00
parent 31fcc1a711
commit 5aa0f05a33

View File

@@ -1,4 +1,4 @@
From d108e94a713fde8c79082202471c6c92e3b7f276 Mon Sep 17 00:00:00 2001 From e685c5e8e9c7355ee8c36fa2d567bbdb3b4af5fe Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 16:01:29 +0100 Date: Sat, 28 Feb 2026 16:01:29 +0100
Subject: [PATCH 2/2] ns: announce child frame completion candidates for Subject: [PATCH 2/2] ns: announce child frame completion candidates for
@@ -17,6 +17,10 @@ the overlay patch to identify "current", "selected", and
"selection" faces. "selection" faces.
Safety measures: Safety measures:
- Use record_unwind_current_buffer / set_buffer_internal_1 to
temporarily switch to the child frame buffer before calling
Fbuffer_substring_no_properties (which operates on current_buffer).
All return paths call unbind_to to restore the original buffer.
- The re-entrance guard (accessibilityUpdating) MUST come before the - The re-entrance guard (accessibilityUpdating) MUST come before the
child frame dispatch, because Lisp calls in the scan function can child frame dispatch, because Lisp calls in the scan function can
trigger redisplay. trigger redisplay.
@@ -43,8 +47,8 @@ memory management complexity in static storage.
handler for FRAME_PARENT_FRAME frames, under re-entrance guard. handler for FRAME_PARENT_FRAME frames, under re-entrance guard.
--- ---
src/nsterm.h | 1 + src/nsterm.h | 1 +
src/nsterm.m | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/nsterm.m | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 193 insertions(+), 1 deletion(-) 2 files changed, 205 insertions(+), 1 deletion(-)
diff --git a/src/nsterm.h b/src/nsterm.h diff --git a/src/nsterm.h b/src/nsterm.h
index 5c15639..21b2823 100644 index 5c15639..21b2823 100644
@@ -59,10 +63,10 @@ index 5c15639..21b2823 100644
@end @end
diff --git a/src/nsterm.m b/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m
index d13c5c7..0b200f9 100644 index d13c5c7..9432c9b 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -7066,6 +7066,98 @@ ns_ax_selected_overlay_text (struct buffer *b, @@ -7066,6 +7066,110 @@ ns_ax_selected_overlay_text (struct buffer *b,
} }
@@ -85,13 +89,23 @@ index d13c5c7..0b200f9 100644
+ if (beg >= end) + if (beg >= end)
+ return nil; + return nil;
+ +
+ /* Temporarily switch to the child frame buffer.
+ Fbuffer_substring_no_properties operates on current_buffer,
+ which may be a different buffer (e.g., the parent frame's). */
+ ptrdiff_t count = SPECPDL_INDEX ();
+ record_unwind_current_buffer ();
+ set_buffer_internal_1 (b);
+
+ /* Get buffer text as a Lisp string for efficient scanning. + /* Get buffer text as a Lisp string for efficient scanning.
+ The buffer is a small completion popup (typically < 20 lines). */ + The buffer is a small completion popup (typically < 20 lines). */
+ Lisp_Object str + Lisp_Object str
+ = Fbuffer_substring_no_properties (make_fixnum (beg), + = Fbuffer_substring_no_properties (make_fixnum (beg),
+ make_fixnum (end)); + make_fixnum (end));
+ if (!STRINGP (str) || SCHARS (str) == 0) + if (!STRINGP (str) || SCHARS (str) == 0)
+ {
+ unbind_to (count, Qnil);
+ return nil; + return nil;
+ }
+ +
+ /* Scan newlines (same pattern as ns_ax_selected_overlay_text). + /* Scan newlines (same pattern as ns_ax_selected_overlay_text).
+ The data pointer is used only in this loop, before Lisp calls. */ + The data pointer is used only in this loop, before Lisp calls. */
@@ -149,11 +163,13 @@ index d13c5c7..0b200f9 100644
+ if ([text length] > 0) + if ([text length] > 0)
+ { + {
+ *out_line_index = li; + *out_line_index = li;
+ unbind_to (count, Qnil);
+ return text; + return text;
+ } + }
+ } + }
+ } + }
+ +
+ unbind_to (count, Qnil);
+ return nil; + return nil;
+} +}
+ +
@@ -161,7 +177,7 @@ index d13c5c7..0b200f9 100644
/* Build accessibility text for window W, skipping invisible text. /* Build accessibility text for window W, skipping invisible text.
Populates *OUT_START with the buffer start charpos. Populates *OUT_START with the buffer start charpos.
Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS
@@ -12299,6 +12391,93 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12299,6 +12403,93 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
The existing elements carry cached state (modiff, point) from the The existing elements carry cached state (modiff, point) from the
previous redisplay cycle. Rebuilding first would create fresh previous redisplay cycle. Rebuilding first would create fresh
elements with current values, making change detection impossible. */ elements with current values, making change detection impossible. */
@@ -255,7 +271,7 @@ index d13c5c7..0b200f9 100644
- (void)postAccessibilityUpdates - (void)postAccessibilityUpdates
{ {
NSTRACE ("[EmacsView postAccessibilityUpdates]"); NSTRACE ("[EmacsView postAccessibilityUpdates]");
@@ -12309,11 +12488,23 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view, @@ -12309,11 +12500,23 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
/* Re-entrance guard: VoiceOver callbacks during notification posting /* Re-entrance guard: VoiceOver callbacks during notification posting
can trigger redisplay, which calls ns_update_end, which calls us can trigger redisplay, which calls ns_update_end, which calls us