Fix patch after 3-reviewer pipeline review

- BLOCKER: real_this_command → Vreal_this_command (DEFVAR_LISP uses V prefix)
- Thread safety: setAccessibilitySelectedTextRange dispatches to main thread
- Defensive: 7 new BUFFERP(w->contents) guards before XBUFFER calls

Reviewed by: symbol checker, logic/memory reviewer, ABI/build reviewer
Verified: git apply --check OK, zero real_this_command refs, dispatch_async present
This commit is contained in:
2026-02-26 22:27:25 +01:00
parent 3c0a68cfb9
commit 97776b5141

View File

@@ -159,7 +159,7 @@ index 932d209..da40369 100644
ns_focus (f, NULL, 0); ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -6849,214 +6885,1777 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) @@ -6849,214 +6885,1801 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
/* ========================================================================== /* ==========================================================================
@@ -196,6 +196,11 @@ index 932d209..da40369 100644
+ return @""; + return @"";
+ } + }
+ +
+ if (!BUFFERP (w->contents))
+ {
+ *out_start = 0;
+ return @"";
+ }
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b) + if (!b)
+ { + {
@@ -629,7 +634,7 @@ index 932d209..da40369 100644
- NSView *buttons; - NSView *buttons;
- BOOL canceled; - BOOL canceled;
-#endif -#endif
+ if (!SYMBOLP (real_this_command)) + if (!SYMBOLP (Vreal_this_command))
+ return false; + return false;
-#ifdef NS_IMPL_GNUSTEP -#ifdef NS_IMPL_GNUSTEP
@@ -639,7 +644,7 @@ index 932d209..da40369 100644
-#endif -#endif
+ Lisp_Object next = intern ("next-line"); + Lisp_Object next = intern ("next-line");
+ Lisp_Object prev = intern ("previous-line"); + Lisp_Object prev = intern ("previous-line");
+ return EQ (real_this_command, next) || EQ (real_this_command, prev); + return EQ (Vreal_this_command, next) || EQ (Vreal_this_command, prev);
+} +}
-#ifdef NS_IMPL_COCOA -#ifdef NS_IMPL_COCOA
@@ -833,6 +838,8 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return; + return;
+ +
+ if (!BUFFERP (w->contents))
+ return;
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b) + if (!b)
+ return; + return;
@@ -1004,6 +1011,8 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return @""; + return @"";
+ +
+ if (!BUFFERP (w->contents))
+ return @"";
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b || NILP (BVAR (b, mark_active))) + if (!b || NILP (BVAR (b, mark_active)))
+ return @""; + return @"";
@@ -1022,6 +1031,8 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return NSMakeRange (0, 0); + return NSMakeRange (0, 0);
+ +
+ if (!BUFFERP (w->contents))
+ return 0;
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b) + if (!b)
+ return NSMakeRange (0, 0); + return NSMakeRange (0, 0);
@@ -1046,54 +1057,63 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return; + return;
+ +
+ struct buffer *b = XBUFFER (w->contents); + if (!BUFFERP (w->contents))
+ if (!b)
+ return; + return;
+ +
+ [self ensureTextCache]; + dispatch_async (dispatch_get_main_queue (), ^{
+ struct window *w2 = self.emacsWindow;
+ if (!w2 || !WINDOW_LEAF_P (w2))
+ return;
+ +
+ /* Convert accessibility index to buffer charpos via mapping. */ + if (!BUFFERP (w2->contents))
+ ptrdiff_t charpos = [self charposForAccessibilityIndex:range.location]; + return;
+ struct buffer *b = XBUFFER (w2->contents);
+ +
+ /* Clamp to buffer bounds. */ + [self ensureTextCache];
+ if (charpos < BUF_BEGV (b))
+ charpos = BUF_BEGV (b);
+ if (charpos > BUF_ZV (b))
+ charpos = BUF_ZV (b);
+ +
+ block_input (); + /* Convert accessibility index to buffer charpos via mapping. */
+ ptrdiff_t charpos = [self charposForAccessibilityIndex:range.location];
+ +
+ /* Move point directly in the buffer. Use set_point_both which + /* Clamp to buffer bounds. */
+ operates on the current buffer — temporarily switch if needed. */ + if (charpos < BUF_BEGV (b))
+ struct buffer *oldb = current_buffer; + charpos = BUF_BEGV (b);
+ if (b != current_buffer) + if (charpos > BUF_ZV (b))
+ set_buffer_internal_1 (b); + charpos = BUF_ZV (b);
+ +
+ SET_PT_BOTH (charpos, CHAR_TO_BYTE (charpos)); + block_input ();
+ +
+ /* Keep mark state aligned with requested selection range. */ + /* Move point directly in the buffer. Use set_point_both which
+ if (range.length > 0) + operates on the current buffer — temporarily switch if needed. */
+ { + struct buffer *oldb = current_buffer;
+ ptrdiff_t mark_charpos = [self charposForAccessibilityIndex: + if (b != current_buffer)
+ range.location + range.length]; + set_buffer_internal_1 (b);
+ if (mark_charpos > BUF_ZV (b))
+ mark_charpos = BUF_ZV (b);
+ Fset_marker (BVAR (b, mark), make_fixnum (mark_charpos),
+ Fcurrent_buffer ());
+ bset_mark_active (b, Qt);
+ }
+ else
+ bset_mark_active (b, Qnil);
+ +
+ if (b != oldb) + SET_PT_BOTH (charpos, CHAR_TO_BYTE (charpos));
+ set_buffer_internal_1 (oldb);
+ +
+ unblock_input (); + /* Keep mark state aligned with requested selection range. */
+ if (range.length > 0)
+ {
+ ptrdiff_t mark_charpos = [self charposForAccessibilityIndex:
+ range.location + range.length];
+ if (mark_charpos > BUF_ZV (b))
+ mark_charpos = BUF_ZV (b);
+ Fset_marker (BVAR (b, mark), make_fixnum (mark_charpos),
+ Fcurrent_buffer ());
+ bset_mark_active (b, Qt);
+ }
+ else
+ bset_mark_active (b, Qnil);
+ +
+ /* Update cached state so the next notification cycle doesn't + if (b != oldb)
+ re-announce this movement. */ + set_buffer_internal_1 (oldb);
+ self.cachedPoint = charpos; +
+ self.cachedMarkActive = (range.length > 0); + unblock_input ();
+
+ /* Update cached state so the next notification cycle doesn't
+ re-announce this movement. */
+ self.cachedPoint = charpos;
+ self.cachedMarkActive = (range.length > 0);
+ });
+} +}
+ +
+- (void)setAccessibilityFocused:(BOOL)flag +- (void)setAccessibilityFocused:(BOOL)flag
@@ -1133,6 +1153,8 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return 0; + return 0;
+ +
+ if (!BUFFERP (w->contents))
+ return 0;
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b) + if (!b)
+ return 0; + return 0;
@@ -1367,6 +1389,8 @@ index 932d209..da40369 100644
+ if (!w || !WINDOW_LEAF_P (w)) + if (!w || !WINDOW_LEAF_P (w))
+ return; + return;
+ +
+ if (!BUFFERP (w->contents))
+ return;
+ struct buffer *b = XBUFFER (w->contents); + struct buffer *b = XBUFFER (w->contents);
+ if (!b) + if (!b)
+ return; + return;
@@ -2076,7 +2100,7 @@ index 932d209..da40369 100644
- (void)keyDown: (NSEvent *)theEvent - (void)keyDown: (NSEvent *)theEvent
{ {
@@ -8237,6 +9836,28 @@ ns_in_echo_area (void) @@ -8237,6 +9860,28 @@ ns_in_echo_area (void)
XSETFRAME (event.frame_or_window, emacsframe); XSETFRAME (event.frame_or_window, emacsframe);
kbd_buffer_store_event (&event); kbd_buffer_store_event (&event);
ns_send_appdefined (-1); // Kick main loop ns_send_appdefined (-1); // Kick main loop
@@ -2105,7 +2129,7 @@ index 932d209..da40369 100644
} }
@@ -9474,6 +11095,298 @@ ns_in_echo_area (void) @@ -9474,6 +11119,298 @@ ns_in_echo_area (void)
return fs_state; return fs_state;
} }
@@ -2404,7 +2428,7 @@ index 932d209..da40369 100644
@end /* EmacsView */ @end /* EmacsView */
@@ -9941,6 +11854,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) @@ -9941,6 +11878,14 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return [super accessibilityAttributeValue:attribute]; return [super accessibilityAttributeValue:attribute];
} }