From: Francis De Brabandere <francisdb@gmail.com> Treat '(' after tEMPTYBRACKETS as an argument list opener in the lexer, so that expressions like GetArr()(0) or dict.Keys()(i) parse correctly. Also dereference VT_BYREF|VT_VARIANT results in vcall so chained indexing on call results works at runtime. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58051 --- dlls/vbscript/interp.c | 9 ++++++++- dlls/vbscript/lex.c | 3 ++- dlls/vbscript/tests/lang.vbs | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 779f3f881a5..8389c6b9704 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -708,13 +708,20 @@ static HRESULT interp_icallv(exec_ctx_t *ctx) static HRESULT interp_vcall(exec_ctx_t *ctx) { const unsigned arg_cnt = ctx->instr->arg1.uint; - VARIANT res, *v; + VARIANT res = {0}, *v; HRESULT hres; TRACE("\n"); v = stack_pop(ctx); hres = variant_call(ctx, v, arg_cnt, &res); + if(SUCCEEDED(hres) && V_VT(&res) == (VT_BYREF|VT_VARIANT)) { + VARIANT tmp; + V_VT(&tmp) = VT_EMPTY; + hres = VariantCopyInd(&tmp, &res); + if(SUCCEEDED(hres)) + res = tmp; + } VariantClear(v); if(FAILED(hres)) return hres; diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 75838ac586a..d595bda7fa0 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -465,7 +465,8 @@ static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) * Parser can't predict if bracket is part of argument expression or an argument * in call expression. We predict it here instead. */ - if(ctx->last_token == tIdentifier || ctx->last_token == ')' || ctx->last_token == tME) + if(ctx->last_token == tIdentifier || ctx->last_token == ')' || ctx->last_token == tME + || ctx->last_token == tEMPTYBRACKETS) return '('; return tEXPRLBRACKET; case '"': diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 4374d7b1f25..40ebe7f23fd 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -1659,6 +1659,26 @@ ok arr2(1,2) = 2, "arr2(1,2) = " & arr2(1,2) x = Array(Array(3)) call ok(x(0)(0) = 3, "x(0)(0) = " & x(0)(0)) +Function GetABC() + GetABC = Array("a", "b", "c") +End Function +call ok(GetABC()(0) = "a", "GetABC()(0) = " & GetABC()(0)) +call ok(GetABC()(1) = "b", "GetABC()(1) = " & GetABC()(1)) +call ok(GetABC()(2) = "c", "GetABC()(2) = " & GetABC()(2)) + +Function GetNested() + GetNested = Array(Array(1, 2), Array(3, 4)) +End Function +call ok(GetNested()(0)(0) = 1, "GetNested()(0)(0) = " & GetNested()(0)(0)) +call ok(GetNested()(0)(1) = 2, "GetNested()(0)(1) = " & GetNested()(0)(1)) +call ok(GetNested()(1)(0) = 3, "GetNested()(1)(0) = " & GetNested()(1)(0)) +call ok(GetNested()(1)(1) = 4, "GetNested()(1)(1) = " & GetNested()(1)(1)) + +x = GetABC()(0) & GetABC()(2) +call ok(x = "ac", "GetABC()(0) & GetABC()(2) = " & x) + +call ok(Array(10,20,30)(1) = 20, "Array(10,20,30)(1) = " & Array(10,20,30)(1)) + function seta0(arr) arr(0) = 2 seta0 = 1 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10362