diff options
author | Bram Moolenaar <Bram@vim.org> | 2023-06-10 16:45:13 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2023-06-10 16:45:13 +0100 |
commit | 5ca05fa59e587f9724306d4788c5dde07fc7225b (patch) | |
tree | 73e72af12e3e1579a0c3530554747b0639626341 | |
parent | f07d1a7108f29068efeb61d91454c4120ab5ae6c (diff) |
patch 9.0.1624: crash when calling object constructorv9.0.1624
Problem: Crash when calling object constructor from legacy script. (Israel
Chauca Fuentes)
Solution: Pass a pointer for "ufunc". (closes #12502)
-rw-r--r-- | src/structs.h | 4 | ||||
-rw-r--r-- | src/testdir/test_vim9_class.vim | 23 | ||||
-rw-r--r-- | src/userfunc.c | 13 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 38 insertions, 4 deletions
diff --git a/src/structs.h b/src/structs.h index 3a32bc595d..ccef537040 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2184,7 +2184,9 @@ typedef struct { linenr_T fe_lastline; // last line of range int *fe_doesrange; // if not NULL: return: function handled range int fe_evaluate; // actually evaluate expressions - partial_T *fe_partial; // for extra arguments + ufunc_T *fe_ufunc; // function to be called, when NULL lookup by + // name + partial_T *fe_partial; // for "dict" and extra arguments dict_T *fe_selfdict; // Dictionary for "self" object_T *fe_object; // object, e.g. for "this.Func()" typval_T *fe_basetv; // base for base->method() diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 1d0d77b298..00b843206e 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -1767,6 +1767,29 @@ def Test_closure_in_class() v9.CheckScriptSuccess(lines) enddef +def Test_call_constructor_from_legacy() + var lines =<< trim END + vim9script + + var newCalled = 'false' + + class A + def new() + newCalled = 'true' + enddef + endclass + + export def F(options = {}): any + return A + enddef + + g:p = F() + legacy call p.new() + assert_equal('true', newCalled) + END + v9.CheckScriptSuccess(lines) +enddef + def Test_defer_with_object() var lines =<< trim END vim9script diff --git a/src/userfunc.c b/src/userfunc.c index 8facd2fdfd..127588469a 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3666,6 +3666,9 @@ call_func( if (partial != NULL) fp = partial->pt_func; if (fp == NULL) + fp = funcexe->fe_ufunc; + + if (fp == NULL) { // Make a copy of the name, if it comes from a funcref variable it // could be changed or deleted in the called function. @@ -4161,8 +4164,10 @@ trans_function_name_ext( if (lv.ll_ufunc != NULL) { - *ufunc = lv.ll_ufunc; + if (ufunc != NULL) + *ufunc = lv.ll_ufunc; name = vim_strsave(lv.ll_ufunc->uf_name); + *pp = end; goto theend; } @@ -5915,7 +5920,7 @@ ex_call_inner( char_u *name, char_u **arg, char_u *startarg, - funcexe_T *funcexe_init, + funcexe_T *funcexe_init, evalarg_T *evalarg) { linenr_T lnum; @@ -6204,6 +6209,7 @@ ex_call(exarg_T *eap) int len; int failed = FALSE; funcdict_T fudi; + ufunc_T *ufunc = NULL; partial_T *partial = NULL; evalarg_T evalarg; type_T *type = NULL; @@ -6227,7 +6233,7 @@ ex_call(exarg_T *eap) } tofree = trans_function_name_ext(&arg, NULL, FALSE, TFN_INT, - &fudi, &partial, vim9script ? &type : NULL, NULL); + &fudi, &partial, vim9script ? &type : NULL, &ufunc); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. @@ -6275,6 +6281,7 @@ ex_call(exarg_T *eap) CLEAR_FIELD(funcexe); funcexe.fe_check_type = type; + funcexe.fe_ufunc = ufunc; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; funcexe.fe_firstline = eap->line1; diff --git a/src/version.c b/src/version.c index 8d38d36e9a..e8ff7e704b 100644 --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1624, +/**/ 1623, /**/ 1622, |