Patch 9.0.0990
Problem:    Callback name argument is changed by setqflist().
Solution:   Use the expanded function name for the callback, do not store it
            in the argument. (closes #11653)
Files:      src/evalvars.c, src/change.c, src/job.c, src/option.c,
            src/popupwin.c, src/quickfix.c, src/time.c,
            src/testdir/test_quickfix.vim


*** ../vim-9.0.0989/src/evalvars.c      2022-11-28 18:51:38.963571609 +0000
--- src/evalvars.c      2022-12-02 15:24:19.477669104 +0000
***************
*** 4792,4800 ****
  
  /*
   * Get a callback from "arg".  It can be a Funcref or a function name.
!  * When "arg" is zero return an empty string.
!  * "cb_name" is not allocated.
!  * "cb_name" is set to NULL for an invalid argument.
   */
      callback_T
  get_callback(typval_T *arg)
--- 4792,4800 ----
  
  /*
   * Get a callback from "arg".  It can be a Funcref or a function name.
!  * When "arg" is zero "res.cb_name" is set to an empty string.
!  * If "res.cb_name" is allocated then "res.cb_free_name" is set to TRUE.
!  * "res.cb_name" is set to NULL for an invalid argument.
   */
      callback_T
  get_callback(typval_T *arg)
***************
*** 4802,4808 ****
      callback_T  res;
      int               r = OK;
  
!     res.cb_free_name = FALSE;
      if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
      {
        res.cb_partial = arg->vval.v_partial;
--- 4802,4808 ----
      callback_T  res;
      int               r = OK;
  
!     CLEAR_FIELD(res);
      if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
      {
        res.cb_partial = arg->vval.v_partial;
***************
*** 4811,4835 ****
      }
      else
      {
-       res.cb_partial = NULL;
        if (arg->v_type == VAR_STRING && arg->vval.v_string != NULL
                                               && isdigit(*arg->vval.v_string))
            r = FAIL;
        else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
        {
            if (arg->v_type == VAR_STRING)
            {
!               char_u *name;
! 
!               name = get_scriptlocal_funcname(arg->vval.v_string);
                if (name != NULL)
                {
!                   vim_free(arg->vval.v_string);
!                   arg->vval.v_string = name;
                }
            }
- 
-           res.cb_name = arg->vval.v_string;
            func_ref(res.cb_name);
        }
        else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
--- 4811,4831 ----
      }
      else
      {
        if (arg->v_type == VAR_STRING && arg->vval.v_string != NULL
                                               && isdigit(*arg->vval.v_string))
            r = FAIL;
        else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
        {
+           res.cb_name = arg->vval.v_string;
            if (arg->v_type == VAR_STRING)
            {
!               char_u *name = get_scriptlocal_funcname(arg->vval.v_string);
                if (name != NULL)
                {
!                   res.cb_name = name;
!                   res.cb_free_name = TRUE;
                }
            }
            func_ref(res.cb_name);
        }
        else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
*** ../vim-9.0.0989/src/change.c        2022-11-02 13:30:37.530314524 +0000
--- src/change.c        2022-12-02 15:29:45.585756816 +0000
***************
*** 259,264 ****
--- 259,266 ----
      buf->b_listener = lnr;
  
      set_callback(&lnr->lr_callback, &callback);
+     if (callback.cb_free_name)
+       vim_free(callback.cb_name);
  
      lnr->lr_id = ++next_listener_id;
      rettv->vval.v_number = lnr->lr_id;
*** ../vim-9.0.0989/src/job.c   2022-06-19 13:07:36.000000000 +0100
--- src/job.c   2022-12-02 15:48:00.718449900 +0000
***************
*** 74,105 ****
      CLEAR_POINTER(opt);
  }
  
  /*
   * Free any members of a jobopt_T.
   */
      void
  free_job_options(jobopt_T *opt)
  {
!     if (opt->jo_callback.cb_partial != NULL)
!       partial_unref(opt->jo_callback.cb_partial);
!     else if (opt->jo_callback.cb_name != NULL)
!       func_unref(opt->jo_callback.cb_name);
!     if (opt->jo_out_cb.cb_partial != NULL)
!       partial_unref(opt->jo_out_cb.cb_partial);
!     else if (opt->jo_out_cb.cb_name != NULL)
!       func_unref(opt->jo_out_cb.cb_name);
!     if (opt->jo_err_cb.cb_partial != NULL)
!       partial_unref(opt->jo_err_cb.cb_partial);
!     else if (opt->jo_err_cb.cb_name != NULL)
!       func_unref(opt->jo_err_cb.cb_name);
!     if (opt->jo_close_cb.cb_partial != NULL)
!       partial_unref(opt->jo_close_cb.cb_partial);
!     else if (opt->jo_close_cb.cb_name != NULL)
!       func_unref(opt->jo_close_cb.cb_name);
!     if (opt->jo_exit_cb.cb_partial != NULL)
!       partial_unref(opt->jo_exit_cb.cb_partial);
!     else if (opt->jo_exit_cb.cb_name != NULL)
!       func_unref(opt->jo_exit_cb.cb_name);
      if (opt->jo_env != NULL)
        dict_unref(opt->jo_env);
  }
--- 74,104 ----
      CLEAR_POINTER(opt);
  }
  
+     static void
+ unref_job_callback(callback_T *cb)
+ {
+     if (cb->cb_partial != NULL)
+       partial_unref(cb->cb_partial);
+     else if (cb->cb_name != NULL)
+     {
+       func_unref(cb->cb_name);
+       if (cb->cb_free_name)
+           vim_free(cb->cb_name);
+     }
+ }
+ 
  /*
   * Free any members of a jobopt_T.
   */
      void
  free_job_options(jobopt_T *opt)
  {
!     unref_job_callback(&opt->jo_callback);
!     unref_job_callback(&opt->jo_out_cb);
!     unref_job_callback(&opt->jo_err_cb);
!     unref_job_callback(&opt->jo_close_cb);
!     unref_job_callback(&opt->jo_exit_cb);
! 
      if (opt->jo_env != NULL)
        dict_unref(opt->jo_env);
  }
***************
*** 1687,1692 ****
--- 1686,1693 ----
  
      free_callback(&buf->b_prompt_callback);
      set_callback(&buf->b_prompt_callback, &callback);
+     if (callback.cb_free_name)
+       vim_free(callback.cb_name);
  }
  
  /*
***************
*** 1714,1719 ****
--- 1715,1722 ----
  
      free_callback(&buf->b_prompt_interrupt);
      set_callback(&buf->b_prompt_interrupt, &callback);
+     if (callback.cb_free_name)
+       vim_free(callback.cb_name);
  }
  
  
*** ../vim-9.0.0989/src/option.c        2022-11-28 11:36:46.295659899 +0000
--- src/option.c        2022-12-02 15:41:12.994213830 +0000
***************
*** 7370,7375 ****
--- 7370,7377 ----
  
      free_callback(optcb);
      set_callback(optcb, &cb);
+     if (cb.cb_free_name)
+       vim_free(cb.cb_name);
      free_tv(tv);
  
      // when using Vim9 style "import.funcname" it needs to be expanded to
*** ../vim-9.0.0989/src/popupwin.c      2022-10-14 20:09:00.895207512 +0100
--- src/popupwin.c      2022-12-02 15:44:28.446338356 +0000
***************
*** 444,450 ****
      if (get_lambda_tv_and_compile(&ptr, &tv, FALSE, &EVALARG_EVALUATE) == OK)
      {
        wp->w_popup_timer = create_timer(time, 0);
!       wp->w_popup_timer->tr_callback = get_callback(&tv);
        clear_tv(&tv);
      }
  }
--- 444,456 ----
      if (get_lambda_tv_and_compile(&ptr, &tv, FALSE, &EVALARG_EVALUATE) == OK)
      {
        wp->w_popup_timer = create_timer(time, 0);
!       callback_T cb = get_callback(&tv);
!       if (cb.cb_name != NULL && !cb.cb_free_name)
!       {
!           cb.cb_name = vim_strsave(cb.cb_name);
!           cb.cb_free_name = TRUE;
!       }
!       wp->w_popup_timer->tr_callback = cb;
        clear_tv(&tv);
      }
  }
***************
*** 961,966 ****
--- 967,974 ----
        {
            free_callback(&wp->w_filter_cb);
            set_callback(&wp->w_filter_cb, &callback);
+           if (callback.cb_free_name)
+               vim_free(callback.cb_name);
        }
      }
      nr = dict_get_bool(dict, "mapping", -1);
***************
*** 990,995 ****
--- 998,1005 ----
        {
            free_callback(&wp->w_close_cb);
            set_callback(&wp->w_close_cb, &callback);
+           if (callback.cb_free_name)
+               vim_free(callback.cb_name);
        }
      }
  }
***************
*** 2229,2235 ****
--- 2239,2249 ----
        tv.vval.v_string = (char_u *)"popup_filter_menu";
        callback = get_callback(&tv);
        if (callback.cb_name != NULL)
+       {
            set_callback(&wp->w_filter_cb, &callback);
+           if (callback.cb_free_name)
+               vim_free(callback.cb_name);
+       }
  
        wp->w_p_wrap = 0;
        wp->w_popup_flags |= POPF_CURSORLINE;
*** ../vim-9.0.0989/src/quickfix.c      2022-11-28 20:34:47.704140309 +0000
--- src/quickfix.c      2022-12-02 15:43:06.150288994 +0000
***************
*** 7633,7639 ****
--- 7633,7643 ----
      free_callback(&qfl->qf_qftf_cb);
      cb = get_callback(&di->di_tv);
      if (cb.cb_name != NULL && *cb.cb_name != NUL)
+     {
        set_callback(&qfl->qf_qftf_cb, &cb);
+       if (cb.cb_free_name)
+           vim_free(cb.cb_name);
+     }
  
      return OK;
  }
*** ../vim-9.0.0989/src/time.c  2022-11-30 18:11:52.694904295 +0000
--- src/time.c  2022-12-02 15:39:27.422134506 +0000
***************
*** 908,913 ****
--- 908,915 ----
      else
      {
        set_callback(&timer->tr_callback, &callback);
+       if (callback.cb_free_name)
+           vim_free(callback.cb_name);
        rettv->vval.v_number = (varnumber_T)timer->tr_id;
      }
  }
*** ../vim-9.0.0989/src/testdir/test_quickfix.vim       2022-11-28 
11:36:46.299659897 +0000
--- src/testdir/test_quickfix.vim       2022-12-02 15:26:46.093712365 +0000
***************
*** 6387,6391 ****
--- 6387,6403 ----
    call setqflist([], 'f')
  endfunc
  
+ func s:QfTf(_)
+ endfunc
+ 
+ func Test_setqflist_cb_arg()
+   " This was changing the callback name in the dictionary.
+   let d = #{quickfixtextfunc: 's:QfTf'}
+   call setqflist([], 'a', d)
+   call assert_equal('s:QfTf', d.quickfixtextfunc)
+ 
+   call setqflist([], 'f')
+ endfunc
+ 
  
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.0989/src/version.c       2022-12-02 15:06:03.740761560 +0000
--- src/version.c       2022-12-02 15:16:34.777460477 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     990,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
206. You religiously respond immediately to e-mail, while ignoring
     your growing pile of snail mail.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221202155909.311C71C007B%40moolenaar.net.

Raspunde prin e-mail lui