diff options
| author | Stefan Monnier | 2018-03-23 11:29:06 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2018-06-03 12:48:14 -0400 |
| commit | ed962f2b8a2f63c7dbf31ec5df3c915703dd571d (patch) | |
| tree | 880aa4dab830e5e7699e6eace5c0a1097a091baa /src/buffer.c | |
| parent | 3ba5fc2bbec3f0f64c7afc1b05c9016710805463 (diff) | |
| download | emacs-ed962f2b8a2f63c7dbf31ec5df3c915703dd571d.tar.gz emacs-ed962f2b8a2f63c7dbf31ec5df3c915703dd571d.zip | |
Fix bug#30846, along with misc cleanups found along the way
* test/src/data-tests.el (data-tests-kill-all-local-variables): New test.
* src/buffer.c (swap_out_buffer_local_variables): Remove.
Fuse the body of its loop into that of reset_buffer_local_variables.
(Fkill_buffer, Fkill_all_local_variables): Don't call it any more.
(reset_buffer_local_variables): Make sure the buffer's local binding
is swapped out before removing it from the alist (bug#30846).
Call watchers before actually killing the var.
* src/data.c (Fmake_local_variable): Simplify.
Use swap_in_global_binding to swap out any local binding, instead of
a mix of find_symbol_value followed by messing with where&found.
Don't call swap_in_symval_forwarding since the currently swapped
binding is never one we've modified.
(Fkill_local_variable): Use swap_in_global_binding rather than messing
with where&found to try and trick find_symbol_value into doing the same.
* src/alloc.c (mark_localized_symbol): 'where' can't be a frame any more.
(cherry picked from commit 3ddff080341580eb6fc18d907181e9cc2301f62d)
Diffstat (limited to 'src/buffer.c')
| -rw-r--r-- | src/buffer.c | 55 |
1 files changed, 19 insertions, 36 deletions
diff --git a/src/buffer.c b/src/buffer.c index 9b54e4b7787..b0cee717036 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -108,7 +108,6 @@ int last_per_buffer_idx; | |||
| 108 | static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, | 108 | static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, |
| 109 | bool after, Lisp_Object arg1, | 109 | bool after, Lisp_Object arg1, |
| 110 | Lisp_Object arg2, Lisp_Object arg3); | 110 | Lisp_Object arg2, Lisp_Object arg3); |
| 111 | static void swap_out_buffer_local_variables (struct buffer *b); | ||
| 112 | static void reset_buffer_local_variables (struct buffer *, bool); | 111 | static void reset_buffer_local_variables (struct buffer *, bool); |
| 113 | 112 | ||
| 114 | /* Alist of all buffer names vs the buffers. This used to be | 113 | /* Alist of all buffer names vs the buffers. This used to be |
| @@ -991,10 +990,29 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too) | |||
| 991 | else | 990 | else |
| 992 | { | 991 | { |
| 993 | Lisp_Object tmp, last = Qnil; | 992 | Lisp_Object tmp, last = Qnil; |
| 993 | Lisp_Object buffer; | ||
| 994 | XSETBUFFER (buffer, b); | ||
| 995 | |||
| 994 | for (tmp = BVAR (b, local_var_alist); CONSP (tmp); tmp = XCDR (tmp)) | 996 | for (tmp = BVAR (b, local_var_alist); CONSP (tmp); tmp = XCDR (tmp)) |
| 995 | { | 997 | { |
| 996 | Lisp_Object local_var = XCAR (XCAR (tmp)); | 998 | Lisp_Object local_var = XCAR (XCAR (tmp)); |
| 997 | Lisp_Object prop = Fget (local_var, Qpermanent_local); | 999 | Lisp_Object prop = Fget (local_var, Qpermanent_local); |
| 1000 | Lisp_Object sym = local_var; | ||
| 1001 | |||
| 1002 | /* Watchers are run *before* modifying the var. */ | ||
| 1003 | if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE) | ||
| 1004 | notify_variable_watchers (local_var, Qnil, | ||
| 1005 | Qmakunbound, Fcurrent_buffer ()); | ||
| 1006 | |||
| 1007 | eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED); | ||
| 1008 | /* Need not do anything if some other buffer's binding is | ||
| 1009 | now cached. */ | ||
| 1010 | if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) | ||
| 1011 | { | ||
| 1012 | /* Symbol is set up for this buffer's old local value: | ||
| 1013 | swap it out! */ | ||
| 1014 | swap_in_global_binding (XSYMBOL (sym)); | ||
| 1015 | } | ||
| 998 | 1016 | ||
| 999 | if (!NILP (prop)) | 1017 | if (!NILP (prop)) |
| 1000 | { | 1018 | { |
| @@ -1034,10 +1052,6 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too) | |||
| 1034 | bset_local_var_alist (b, XCDR (tmp)); | 1052 | bset_local_var_alist (b, XCDR (tmp)); |
| 1035 | else | 1053 | else |
| 1036 | XSETCDR (last, XCDR (tmp)); | 1054 | XSETCDR (last, XCDR (tmp)); |
| 1037 | |||
| 1038 | if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE) | ||
| 1039 | notify_variable_watchers (local_var, Qnil, | ||
| 1040 | Qmakunbound, Fcurrent_buffer ()); | ||
| 1041 | } | 1055 | } |
| 1042 | } | 1056 | } |
| 1043 | 1057 | ||
| @@ -1867,7 +1881,6 @@ cleaning up all windows currently displaying the buffer to be killed. */) | |||
| 1867 | won't be protected from GC. They would be protected | 1881 | won't be protected from GC. They would be protected |
| 1868 | if they happened to remain cached in their symbols. | 1882 | if they happened to remain cached in their symbols. |
| 1869 | This gets rid of them for certain. */ | 1883 | This gets rid of them for certain. */ |
| 1870 | swap_out_buffer_local_variables (b); | ||
| 1871 | reset_buffer_local_variables (b, 1); | 1884 | reset_buffer_local_variables (b, 1); |
| 1872 | 1885 | ||
| 1873 | bset_name (b, Qnil); | 1886 | bset_name (b, Qnil); |
| @@ -2737,11 +2750,6 @@ the normal hook `change-major-mode-hook'. */) | |||
| 2737 | { | 2750 | { |
| 2738 | run_hook (Qchange_major_mode_hook); | 2751 | run_hook (Qchange_major_mode_hook); |
| 2739 | 2752 | ||
| 2740 | /* Make sure none of the bindings in local_var_alist | ||
| 2741 | remain swapped in, in their symbols. */ | ||
| 2742 | |||
| 2743 | swap_out_buffer_local_variables (current_buffer); | ||
| 2744 | |||
| 2745 | /* Actually eliminate all local bindings of this buffer. */ | 2753 | /* Actually eliminate all local bindings of this buffer. */ |
| 2746 | 2754 | ||
| 2747 | reset_buffer_local_variables (current_buffer, 0); | 2755 | reset_buffer_local_variables (current_buffer, 0); |
| @@ -2753,31 +2761,6 @@ the normal hook `change-major-mode-hook'. */) | |||
| 2753 | return Qnil; | 2761 | return Qnil; |
| 2754 | } | 2762 | } |
| 2755 | 2763 | ||
| 2756 | /* Make sure no local variables remain set up with buffer B | ||
| 2757 | for their current values. */ | ||
| 2758 | |||
| 2759 | static void | ||
| 2760 | swap_out_buffer_local_variables (struct buffer *b) | ||
| 2761 | { | ||
| 2762 | Lisp_Object oalist, alist, buffer; | ||
| 2763 | |||
| 2764 | XSETBUFFER (buffer, b); | ||
| 2765 | oalist = BVAR (b, local_var_alist); | ||
| 2766 | |||
| 2767 | for (alist = oalist; CONSP (alist); alist = XCDR (alist)) | ||
| 2768 | { | ||
| 2769 | Lisp_Object sym = XCAR (XCAR (alist)); | ||
| 2770 | eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED); | ||
| 2771 | /* Need not do anything if some other buffer's binding is | ||
| 2772 | now cached. */ | ||
| 2773 | if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) | ||
| 2774 | { | ||
| 2775 | /* Symbol is set up for this buffer's old local value: | ||
| 2776 | swap it out! */ | ||
| 2777 | swap_in_global_binding (XSYMBOL (sym)); | ||
| 2778 | } | ||
| 2779 | } | ||
| 2780 | } | ||
| 2781 | 2764 | ||
| 2782 | /* Find all the overlays in the current buffer that contain position POS. | 2765 | /* Find all the overlays in the current buffer that contain position POS. |
| 2783 | Return the number found, and store them in a vector in *VEC_PTR. | 2766 | Return the number found, and store them in a vector in *VEC_PTR. |