Mercurial > vim
diff src/vim9instr.c @ 31920:f1a5e67e9a1b v9.0.1292
patch 9.0.1292: :defer may call the wrong method for an object
Commit: https://github.com/vim/vim/commit/313e4724c3b4f6d7454b45b89da08f83a2a0c77e
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Feb 8 20:55:27 2023 +0000
patch 9.0.1292: :defer may call the wrong method for an object
Problem: :defer may call the wrong method for an object. (Ernie Rael)
Solution: When en object is from a class that extends or implements, figure
out the method to call at runtime. (closes #11910)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 08 Feb 2023 22:00:06 +0100 |
parents | b7a8611dd9fc |
children | e8c60d35fce3 |
line wrap: on
line diff
--- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1328,12 +1328,16 @@ generate_NEWDICT(cctx_T *cctx, int count /* * Generate an ISN_FUNCREF instruction. + * For "obj.Method" "cl" is the class of the object (can be an interface or a + * base class) and "fi" the index of the method on that class. * "isnp" is set to the instruction, so that fr_dfunc_idx can be set later. */ int generate_FUNCREF( cctx_T *cctx, ufunc_T *ufunc, + class_T *cl, + int fi, isn_T **isnp) { isn_T *isn; @@ -1349,17 +1353,23 @@ generate_FUNCREF( *isnp = isn; has_vars = get_loop_var_info(cctx, &loopinfo); - if (ufunc->uf_def_status == UF_NOT_COMPILED || has_vars) + if (ufunc->uf_def_status == UF_NOT_COMPILED || has_vars || cl != NULL) { extra = ALLOC_CLEAR_ONE(funcref_extra_T); if (extra == NULL) return FAIL; isn->isn_arg.funcref.fr_extra = extra; extra->fre_loopvar_info = loopinfo; + if (cl != NULL) + { + extra->fre_class = cl; + ++cl->class_refcount; + extra->fre_method_idx = fi; + } } - if (ufunc->uf_def_status == UF_NOT_COMPILED) + if (ufunc->uf_def_status == UF_NOT_COMPILED || cl != NULL) extra->fre_func_name = vim_strsave(ufunc->uf_name); - else + if (ufunc->uf_def_status != UF_NOT_COMPILED && cl == NULL) { if (isnp == NULL && ufunc->uf_def_status == UF_TO_BE_COMPILED) // compile the function now, we need the uf_dfunc_idx value @@ -2484,6 +2494,8 @@ delete_instr(isn_T *isn) func_unref(name); vim_free(name); } + if (extra->fre_class != NULL) + class_unref(extra->fre_class); vim_free(extra); } }