patch 9.2.1008: Vim9: hang when a line break is used before "->("
Commit:
https://github.com/vim/vim/commit/4b0b53e856d4df9ada397efd49bec5a78b943643
Author: Hirohito Higashi <
h.eas...@gmail.com>
Date: Tue Aug 25 20:18:37 2026 +0000
patch 9.2.1008: Vim9: hang when a line break is used before "->("
Problem: In Vim9 script a line break before "->(" makes Vim hang and
use up memory (SectionCotangentBundle)
Solution: Consume the line break for "->(" as well, and skip white
space after "->" in a compiled function too (Hirohito Higashi).
fixes: #21144
closes: #21147
Co-Authored-By: Claude Opus 5 (1M context) <
nor...@anthropic.com>
Signed-off-by: Hirohito Higashi <
h.eas...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/eval.c b/src/eval.c
index bb6f452b0..0d19330c7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -7591,6 +7591,21 @@ eval_isdictc(int c)
return ASCII_ISALNUM(c) || c == '_';
}
+/*
+ * Return true when "p" points to "->" followed by a method name or a lambda.
+ * Only called for Vim9 script.
+ */
+ static bool
+method_call_follows(char_u *p)
+{
+ if (p[0] != '-' || p[1] != '>')
+ return false;
+
+ char_u *after = skipwhite(p + 2);
+
+ return ASCII_ISALPHA(*after) || *after == '(';
+}
+
/*
* Handle:
* - expr[expr], expr[expr:expr] subscript
@@ -7619,7 +7634,7 @@ handle_subscript(
while (ret == OK)
{
- // When at the end of the line and ".name" or "->{" or "->X" follows in
+ // When at the end of the line and ".name" or a method call follows in
// the next line then consume the line break.
p = eval_next_non_blank(*arg, evalarg, &getnext);
if (getnext
@@ -7627,9 +7642,7 @@ handle_subscript(
&& ((rettv->v_type == VAR_DICT && eval_isdictc(p[1]))
|| rettv->v_type == VAR_CLASS
|| rettv->v_type == VAR_OBJECT))
- || (p[0] == '-' && p[1] == '>' && (p[2] == '{'
- || ASCII_ISALPHA(in_vim9script() ? *skipwhite(p + 2)
- : p[2])))))
+ || method_call_follows(p)))
{
*arg = eval_next_line(*arg, evalarg);
p = *arg;
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 1062df185..3613c1a2e 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -3964,6 +3964,14 @@ def Test_expr9_method_call()
var sorted = [3, 1, 2]
-> sort()
assert_equal([1, 2, 3], sorted)
+
+ var nrs = [1, 2]
+ ->((x) => x)()
+ assert_equal([1, 2], nrs)
+
+ nrs = [3, 4]
+ -> ((x) => x)()
+ assert_equal([3, 4], nrs)
END
v9.CheckDefAndScriptSuccess(lines)
diff --git a/src/version.c b/src/version.c
index 218ee0cc8..80a2f1686 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1008,
/**/
1007,
/**/
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 87a872f58..46d978d44 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -2550,7 +2550,7 @@ compile_subscript(
if (next != NULL &&
((next[0] == '-' && next[1] == '>'
&& (next[2] == '{'
- || next[2] == '('
+ || *skipwhite(next + 2) == '('
|| ASCII_ISALPHA(*skipwhite(next + 2))))
|| (next[0] == '.' && eval_isdictc(next[1]))))
{