Mercurial > vim
comparison src/vim9execute.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 | ffa11e2757e7 |
children | 7b1cbb43506c |
comparison
equal
deleted
inserted
replaced
31919:b1b8848f5bb3 | 31920:f1a5e67e9a1b |
---|---|
4289 if (GA_GROW_FAILS(&ectx->ec_stack, 1)) | 4289 if (GA_GROW_FAILS(&ectx->ec_stack, 1)) |
4290 { | 4290 { |
4291 vim_free(pt); | 4291 vim_free(pt); |
4292 goto theend; | 4292 goto theend; |
4293 } | 4293 } |
4294 if (extra == NULL || extra->fre_func_name == NULL) | 4294 if (extra != NULL && extra->fre_class != NULL) |
4295 { | |
4296 tv = STACK_TV_BOT(-1); | |
4297 if (tv->v_type != VAR_OBJECT) | |
4298 { | |
4299 object_required_error(tv); | |
4300 vim_free(pt); | |
4301 goto on_error; | |
4302 } | |
4303 object_T *obj = tv->vval.v_object; | |
4304 class_T *cl = obj->obj_class; | |
4305 | |
4306 // convert the interface index to the object index | |
4307 int idx = object_index_from_itf_index(extra->fre_class, | |
4308 TRUE, extra->fre_method_idx, cl); | |
4309 ufunc = cl->class_obj_methods[idx]; | |
4310 } | |
4311 else if (extra == NULL || extra->fre_func_name == NULL) | |
4295 { | 4312 { |
4296 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) | 4313 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) |
4297 + funcref->fr_dfunc_idx; | 4314 + funcref->fr_dfunc_idx; |
4298 | 4315 |
4299 ufunc = pt_dfunc->df_ufunc; | 4316 ufunc = pt_dfunc->df_ufunc; |
4300 } | 4317 } |
4301 else | 4318 else |
4319 { | |
4302 ufunc = find_func(extra->fre_func_name, FALSE); | 4320 ufunc = find_func(extra->fre_func_name, FALSE); |
4321 } | |
4303 if (ufunc == NULL) | 4322 if (ufunc == NULL) |
4304 { | 4323 { |
4305 SOURCING_LNUM = iptr->isn_lnum; | 4324 SOURCING_LNUM = iptr->isn_lnum; |
4306 iemsg("ufunc unexpectedly NULL for FUNCREF"); | 4325 iemsg("ufunc unexpectedly NULL for FUNCREF"); |
4307 goto theend; | 4326 goto theend; |
6725 + funcref->fr_dfunc_idx; | 6744 + funcref->fr_dfunc_idx; |
6726 name = df->df_ufunc->uf_name; | 6745 name = df->df_ufunc->uf_name; |
6727 } | 6746 } |
6728 else | 6747 else |
6729 name = extra->fre_func_name; | 6748 name = extra->fre_func_name; |
6730 if (extra == NULL || extra->fre_loopvar_info.lvi_depth == 0) | 6749 if (extra != NULL && extra->fre_class != NULL) |
6750 { | |
6751 smsg("%s%4d FUNCREF %s.%s", pfx, current, | |
6752 extra->fre_class->class_name, name); | |
6753 } | |
6754 else if (extra == NULL | |
6755 || extra->fre_loopvar_info.lvi_depth == 0) | |
6756 { | |
6731 smsg("%s%4d FUNCREF %s", pfx, current, name); | 6757 smsg("%s%4d FUNCREF %s", pfx, current, name); |
6758 } | |
6732 else | 6759 else |
6733 { | 6760 { |
6734 char_u *info = printable_loopvarinfo( | 6761 char_u *info = printable_loopvarinfo( |
6735 &extra->fre_loopvar_info); | 6762 &extra->fre_loopvar_info); |
6736 | 6763 |