1313#include "nvim/buffer.h"
1414#include "nvim/buffer_defs.h"
1515#include "nvim/globals.h"
16+ #include "nvim/memline.h"
1617#include "nvim/memory.h"
1718#include "nvim/memory_defs.h"
1819#include "nvim/option.h"
@@ -101,8 +102,10 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex *
101102}
102103
103104/// Create a dummy buffer and run the FileType autocmd on it.
104- static buf_T * do_ft_buf (char * filetype , aco_save_T * aco , Error * err )
105+ static buf_T * do_ft_buf (const char * filetype , aco_save_T * aco , bool * aco_used , Error * err )
106+ FUNC_ATTR_NONNULL_ARG (2 , 3 , 4 )
105107{
108+ * aco_used = false;
106109 if (filetype == NULL ) {
107110 return NULL ;
108111 }
@@ -114,19 +117,37 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err)
114117 return NULL ;
115118 }
116119
120+ // Open a memline for use by autocommands.
121+ if (ml_open (ftbuf ) == FAIL ) {
122+ api_set_error (err , kErrorTypeException , "Could not load internal buffer" );
123+ return ftbuf ;
124+ }
125+
126+ bufref_T bufref ;
127+ set_bufref (& bufref , ftbuf );
128+
117129 // Set curwin/curbuf to buf and save a few things.
118130 aucmd_prepbuf (aco , ftbuf );
131+ * aco_used = true;
119132
120- TRY_WRAP (err , {
121- set_option_value (kOptBufhidden , STATIC_CSTR_AS_OPTVAL ("hide" ), OPT_LOCAL );
122- set_option_value (kOptBuftype , STATIC_CSTR_AS_OPTVAL ("nofile" ), OPT_LOCAL );
123- set_option_value (kOptSwapfile , BOOLEAN_OPTVAL (false), OPT_LOCAL );
124- set_option_value (kOptModeline , BOOLEAN_OPTVAL (false), OPT_LOCAL ); // 'nomodeline'
133+ set_option_direct (kOptBufhidden , STATIC_CSTR_AS_OPTVAL ("hide" ), OPT_LOCAL , SID_NONE );
134+ set_option_direct (kOptBuftype , STATIC_CSTR_AS_OPTVAL ("nofile" ), OPT_LOCAL , SID_NONE );
135+ assert (ftbuf -> b_ml .ml_mfp -> mf_fd < 0 ); // ml_open() should not have opened swapfile already
136+ ftbuf -> b_p_swf = false;
137+ ftbuf -> b_p_ml = false;
138+ ftbuf -> b_p_ft = xstrdup (filetype );
125139
126- ftbuf -> b_p_ft = xstrdup ( filetype );
140+ TRY_WRAP ( err , {
127141 do_filetype_autocmd (ftbuf , false);
128142 });
129143
144+ if (!bufref_valid (& bufref )) {
145+ if (!ERROR_SET (err )) {
146+ api_set_error (err , kErrorTypeException , "Internal buffer was deleted" );
147+ }
148+ return NULL ;
149+ }
150+
130151 return ftbuf ;
131152}
132153
@@ -163,13 +184,15 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
163184 }
164185
165186 aco_save_T aco ;
187+ bool aco_used ;
166188
167- buf_T * ftbuf = do_ft_buf (filetype , & aco , err );
189+ buf_T * ftbuf = do_ft_buf (filetype , & aco , & aco_used , err );
168190 if (ERROR_SET (err )) {
169- if (ftbuf != NULL ) {
191+ if (aco_used ) {
170192 // restore curwin/curbuf and a few other things
171193 aucmd_restbuf (& aco );
172-
194+ }
195+ if (ftbuf != NULL ) {
173196 assert (curbuf != ftbuf ); // safety check
174197 wipe_buffer (ftbuf , false);
175198 }
@@ -185,9 +208,10 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
185208 OptVal value = get_option_value_for (opt_idx , opt_flags , scope , from , err );
186209
187210 if (ftbuf != NULL ) {
188- // restore curwin/curbuf and a few other things
189- aucmd_restbuf (& aco );
190-
211+ if (aco_used ) {
212+ // restore curwin/curbuf and a few other things
213+ aucmd_restbuf (& aco );
214+ }
191215 assert (curbuf != ftbuf ); // safety check
192216 wipe_buffer (ftbuf , false);
193217 }
0 commit comments