Patch 8.2.1154
Problem:    Vim9: crash when using imported function.
Solution:   Check for a function type.  Set the script context when calling a
            function. (closes #6412)
Files:      src/evalvars.c, src/scriptfile.c, src/proto/scriptfile.pro,
            src/vim9execute.c, src/structs.h, src/testdir/test_vim9_script.vim


*** ../vim-8.2.1153/src/evalvars.c      2020-07-04 17:39:07.506515715 +0200
--- src/evalvars.c      2020-07-07 23:02:08.282700284 +0200
***************
*** 2375,2380 ****
--- 2375,2381 ----
  {
      int               ret = OK;
      typval_T  *tv = NULL;
+     int               foundFunc = FALSE;
      dictitem_T        *v;
      int               cc;
  
***************
*** 2402,2422 ****
        // imported variable from another script
        if (import != NULL)
        {
!           scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
!           svar_T          *sv = ((svar_T *)si->sn_var_vals.ga_data)
                                                    + import->imp_var_vals_idx;
!           tv = sv->sv_tv;
        }
      }
  
!     if (tv == NULL)
      {
!       if (rettv != NULL && verbose)
!           semsg(_(e_undefvar), name);
!       ret = FAIL;
      }
-     else if (rettv != NULL)
-       copy_tv(tv, rettv);
  
      name[len] = cc;
  
--- 2403,2438 ----
        // imported variable from another script
        if (import != NULL)
        {
!           if (import->imp_funcname != NULL)
!           {
!               foundFunc = TRUE;
!               if (rettv != NULL)
!               {
!                   rettv->v_type = VAR_FUNC;
!                   rettv->vval.v_string = vim_strsave(import->imp_funcname);
!               }
!           }
!           else
!           {
!               scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
!               svar_T      *sv = ((svar_T *)si->sn_var_vals.ga_data)
                                                    + import->imp_var_vals_idx;
!               tv = sv->sv_tv;
!           }
        }
      }
  
!     if (!foundFunc)
      {
!       if (tv == NULL)
!       {
!           if (rettv != NULL && verbose)
!               semsg(_(e_undefvar), name);
!           ret = FAIL;
!       }
!       else if (rettv != NULL)
!           copy_tv(tv, rettv);
      }
  
      name[len] = cc;
  
*** ../vim-8.2.1153/src/scriptfile.c    2020-06-24 18:37:28.359249374 +0200
--- src/scriptfile.c    2020-07-07 23:20:05.637463929 +0200
***************
*** 68,74 ****
  /*
   * Add a user function to the execution stack.
   */
!     void
  estack_push_ufunc(ufunc_T *ufunc, long lnum)
  {
      estack_T *entry = estack_push(ETYPE_UFUNC,
--- 68,74 ----
  /*
   * Add a user function to the execution stack.
   */
!     estack_T *
  estack_push_ufunc(ufunc_T *ufunc, long lnum)
  {
      estack_T *entry = estack_push(ETYPE_UFUNC,
***************
*** 76,81 ****
--- 76,82 ----
                                  ? ufunc->uf_name_exp : ufunc->uf_name, lnum);
      if (entry != NULL)
        entry->es_info.ufunc = ufunc;
+     return entry;
  }
  
  /*
***************
*** 97,109 ****
  #endif
  
  /*
!  * Take an item off of the execution stack.
   */
!     void
  estack_pop(void)
  {
!     if (exestack.ga_len > 1)
!       --exestack.ga_len;
  }
  
  /*
--- 98,112 ----
  #endif
  
  /*
!  * Take an item off of the execution stack and return it.
   */
!     estack_T *
  estack_pop(void)
  {
!     if (exestack.ga_len == 0)
!       return NULL;
!     --exestack.ga_len;
!     return ((estack_T *)exestack.ga_data) + exestack.ga_len;
  }
  
  /*
*** ../vim-8.2.1153/src/proto/scriptfile.pro    2020-06-24 18:37:28.359249374 
+0200
--- src/proto/scriptfile.pro    2020-07-07 23:20:43.537290995 +0200
***************
*** 1,9 ****
  /* scriptfile.c */
  void estack_init(void);
  estack_T *estack_push(etype_T type, char_u *name, long lnum);
! void estack_push_ufunc(ufunc_T *ufunc, long lnum);
  int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
! void estack_pop(void);
  char_u *estack_sfile(void);
  void ex_runtime(exarg_T *eap);
  int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u 
*fname, void *ck), void *cookie);
--- 1,9 ----
  /* scriptfile.c */
  void estack_init(void);
  estack_T *estack_push(etype_T type, char_u *name, long lnum);
! estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum);
  int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
! estack_T *estack_pop(void);
  char_u *estack_sfile(void);
  void ex_runtime(exarg_T *eap);
  int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u 
*fname, void *ck), void *cookie);
*** ../vim-8.2.1153/src/vim9execute.c   2020-07-05 16:51:23.610238546 +0200
--- src/vim9execute.c   2020-07-07 23:20:39.237310592 +0200
***************
*** 160,165 ****
--- 160,166 ----
      int           arg_to_add;
      int           vararg_count = 0;
      int           idx;
+     estack_T *entry;
  
      if (dfunc->df_deleted)
      {
***************
*** 230,236 ****
      // Set execution state to the start of the called function.
      ectx->ec_dfunc_idx = cdf_idx;
      ectx->ec_instr = dfunc->df_instr;
!     estack_push_ufunc(dfunc->df_ufunc, 1);
  
      // Decide where to start execution, handles optional arguments.
      init_instr_idx(ufunc, argcount, ectx);
--- 231,244 ----
      // Set execution state to the start of the called function.
      ectx->ec_dfunc_idx = cdf_idx;
      ectx->ec_instr = dfunc->df_instr;
!     entry = estack_push_ufunc(dfunc->df_ufunc, 1);
!     if (entry != NULL)
!     {
!       // Set the script context to the script where the function was defined.
!       // TODO: save more than the SID?
!       entry->es_save_sid = current_sctx.sc_sid;
!       current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid;
!     }
  
      // Decide where to start execution, handles optional arguments.
      init_instr_idx(ufunc, argcount, ectx);
***************
*** 386,394 ****
                                                          + ectx->ec_dfunc_idx;
      int               argcount = ufunc_argcount(dfunc->df_ufunc);
      int               top = ectx->ec_frame_idx - argcount;
  
      // execution context goes one level up
!     estack_pop();
  
      if (handle_closure_in_use(ectx, TRUE) == FAIL)
        return FAIL;
--- 394,405 ----
                                                          + ectx->ec_dfunc_idx;
      int               argcount = ufunc_argcount(dfunc->df_ufunc);
      int               top = ectx->ec_frame_idx - argcount;
+     estack_T  *entry;
  
      // execution context goes one level up
!     entry = estack_pop();
!     if (entry != NULL)
!       current_sctx.sc_sid = entry->es_save_sid;
  
      if (handle_closure_in_use(ectx, TRUE) == FAIL)
        return FAIL;
*** ../vim-8.2.1153/src/structs.h       2020-06-28 18:43:36.296992324 +0200
--- src/structs.h       2020-07-08 14:09:50.231790400 +0200
***************
*** 1905,1910 ****
--- 1905,1913 ----
        AutoPatCmd *aucmd;  // autocommand info
        except_T   *except; // exception info
      } es_info;
+ #if defined(FEAT_EVAL)
+     scid_T    es_save_sid;        // saved sc_sid when calling function
+ #endif
  } estack_T;
  
  // Information returned by get_tty_info().
*** ../vim-8.2.1153/src/testdir/test_vim9_script.vim    2020-07-07 
23:31:31.814366067 +0200
--- src/testdir/test_vim9_script.vim    2020-07-08 14:47:38.266937211 +0200
***************
*** 911,920 ****
    CheckRunVimInTerminal
  
    " call indirectly to avoid compilation error for missing functions
!   call Run_Test_import_fails_without_script()
  endfunc
  
! def Run_Test_import_fails_without_script()
    let export =<< trim END
      vim9script
      export def Foo(): number
--- 911,920 ----
    CheckRunVimInTerminal
  
    " call indirectly to avoid compilation error for missing functions
!   call Run_Test_import_fails_on_command_line()
  endfunc
  
! def Run_Test_import_fails_on_command_line()
    let export =<< trim END
      vim9script
      export def Foo(): number
***************
*** 1013,1018 ****
--- 1013,1047 ----
    delete('Xscript.vim')
  enddef
  
+ " Check that when searcing for "FilterFunc" it doesn't find the import in the
+ " script where FastFilter() is called from.
+ def Test_vim9script_funcref_other_script()
+   let filterLines =<< trim END
+     vim9script
+     export def FilterFunc(idx: number, val: number): bool
+       return idx % 2 == 1
+     enddef
+     export def FastFilter(): list<number>
+       return range(10)->filter('FilterFunc')
+     enddef
+   END
+   writefile(filterLines, 'Xfilter.vim')
+ 
+   let lines =<< trim END
+     vim9script
+     import {FilterFunc, FastFilter} from './Xfilter.vim'
+     def Test()
+       let x: list<number> = FastFilter()
+     enddef
+     Test()
+   END
+   writefile(lines, 'Ximport.vim')
+   assert_fails('source Ximport.vim', 'E121:')
+ 
+   delete('Xfilter.vim')
+   delete('Ximport.vim')
+ enddef
+ 
  def Test_vim9script_reload_delfunc()
    let first_lines =<< trim END
      vim9script
*** ../vim-8.2.1153/src/version.c       2020-07-07 23:31:31.814366067 +0200
--- src/version.c       2020-07-08 15:14:26.962523895 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1154,
  /**/

-- 
Every engineer dreams about saving the universe and having sex with aliens.
This is much more glamorous than the real life of an engineer, which consists
of hiding from the universe and having sex without the participation of other
life forms.                     (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202007081316.068DGmL31340410%40masaka.moolenaar.net.

Raspunde prin e-mail lui