aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/userfunc.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-09-16 23:09:26 +0800
committerGitHub <noreply@github.com>2022-09-16 23:09:26 +0800
commit6b2f0f43b5f9d375d2be1b4eb4784716dd89ec8f (patch)
tree1e53e27a8ca184decab0a7929b80870c7e406832 /src/nvim/eval/userfunc.c
parenta0642ec75e5986af03829ad4f448e300fa40ebb4 (diff)
downloadrneovim-6b2f0f43b5f9d375d2be1b4eb4784716dd89ec8f.tar.gz
rneovim-6b2f0f43b5f9d375d2be1b4eb4784716dd89ec8f.tar.bz2
rneovim-6b2f0f43b5f9d375d2be1b4eb4784716dd89ec8f.zip
fix(eval)!: make Lua Funcref work as method and in substitute() (#20217)
BREAKING CHANGE: When using a Funcref converted from a Lua function as a method in Vim script, the result of the base expression is now passed as the first argument instead of being ignored. vim-patch:8.2.5117: crash when calling a Lua callback from a :def function Problem: Crash when calling a Lua callback from a :def function. (Bohdan Makohin) Solution: Handle FC_CFUNC in call_user_func_check(). (closes vim/vim#10587) https://github.com/vim/vim/commit/7d149f899d423b7bf2b90d7b11ebe3e560c462b9
Diffstat (limited to 'src/nvim/eval/userfunc.c')
-rw-r--r--src/nvim/eval/userfunc.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 30814a8d35..f28af5a6cc 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -1199,6 +1199,34 @@ static bool func_name_refcount(char_u *name)
return isdigit(*name) || *name == '<';
}
+/// Call a user function after checking the arguments.
+static int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv,
+ funcexe_T *funcexe, dict_T *selfdict)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5)
+{
+ if (fp->uf_flags & FC_LUAREF) {
+ return typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv);
+ }
+
+ if ((fp->uf_flags & FC_RANGE) && funcexe->fe_doesrange != NULL) {
+ *funcexe->fe_doesrange = true;
+ }
+ int error;
+ if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
+ error = FCERR_TOOFEW;
+ } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) {
+ error = FCERR_TOOMANY;
+ } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) {
+ error = FCERR_DICT;
+ } else {
+ // Call the user function.
+ call_user_func(fp, argcount, argvars, rettv, funcexe->fe_firstline, funcexe->fe_lastline,
+ (fp->uf_flags & FC_DICT) ? selfdict : NULL);
+ error = FCERR_NONE;
+ }
+ return error;
+}
+
static funccal_entry_T *funccal_stack = NULL;
/// Save the current function call pointer, and set it to NULL.
@@ -1524,8 +1552,6 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
error = FCERR_DELETED;
- } else if (fp != NULL && (fp->uf_flags & FC_LUAREF)) {
- error = typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv);
} else if (fp != NULL) {
if (funcexe->fe_argv_func != NULL) {
// postponed filling in the arguments, do it now
@@ -1534,22 +1560,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
argv_add_base(funcexe->fe_basetv, &argvars, &argcount, argv, &argv_base);
- if (fp->uf_flags & FC_RANGE && funcexe->fe_doesrange != NULL) {
- *funcexe->fe_doesrange = true;
- }
- if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
- error = FCERR_TOOFEW;
- } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) {
- error = FCERR_TOOMANY;
- } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) {
- error = FCERR_DICT;
- } else {
- // Call the user function.
- call_user_func(fp, argcount, argvars, rettv, funcexe->fe_firstline,
- funcexe->fe_lastline,
- (fp->uf_flags & FC_DICT) ? selfdict : NULL);
- error = FCERR_NONE;
- }
+ error = call_user_func_check(fp, argcount, argvars, rettv, funcexe, selfdict);
}
} else if (funcexe->fe_basetv != NULL) {
// expr->method(): Find the method name in the table, call its