closes https://bugs.winehq.org/show_bug.cgi?id=56464
-- v5: vbscript: implement Join()
From: Francis De Brabandere francisdb@gmail.com
--- dlls/vbscript/global.c | 113 +++++++++++++++++++++++++++++++++++- dlls/vbscript/tests/api.vbs | 75 ++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 972d0d2ea0b..e58c8534054 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2581,10 +2581,117 @@ static HRESULT Global_Filter(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, return E_NOTIMPL; }
-static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_Join(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + BSTR string, tmp, str, conv_str = NULL, delimiter = NULL; + SAFEARRAY *sa; + HRESULT hres; + INT i; + UINT string_len, str_len, delimiter_len; + LONG lbound, ubound; + VARIANT *data; + + TRACE("%s %u...\n", debugstr_variant(args), args_cnt); + + assert(1 <= args_cnt && args_cnt <= 2); + + switch(V_VT(args)) { + case VT_NULL: + return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); + case VT_DISPATCH: + return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD); + case VT_VARIANT|VT_ARRAY: + sa = V_ARRAY(args); + break; + case VT_VARIANT|VT_ARRAY|VT_BYREF: + sa = *V_ARRAYREF(args); + break; + default: + return MAKE_VBSERROR(VBSE_TYPE_MISMATCH); + } + + if (args_cnt == 2) + { + if ( V_VT(args+1) == VT_NULL) + return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); + if(V_VT(args+1) != VT_BSTR) + { + hres = to_string(args+1, &delimiter); + if(FAILED(hres)) { + return hres; + } + } + else + delimiter = V_BSTR(args+1); + } + else + delimiter = SysAllocString(L" "); + + if (SafeArrayGetDim(sa) != 1) + return E_NOTIMPL; + + hres = SafeArrayGetLBound(sa, 1, &lbound); + if(FAILED(hres)) + return hres; + + hres = SafeArrayGetUBound(sa, 1, &ubound); + if(FAILED(hres)) + return hres; + + hres = SafeArrayAccessData(sa, (void**)&data); + if (FAILED(hres)) + return hres; + + delimiter_len = SysStringLen(delimiter); + + string = SysAllocString(L""); + + for (i = lbound; i <= ubound; i++) { + if(V_VT(&data[i]) != VT_BSTR) { + hres = to_string(&data[i], &conv_str); + if(FAILED(hres)) { + SafeArrayUnaccessData(sa); + SysFreeString(string); + + if (args_cnt == 2) + if(V_VT(args+1) != VT_BSTR) + SysFreeString(delimiter); + + return hres; + } + str = conv_str; + } + else + str = V_BSTR(&data[i]); + + if (i > lbound) { + string_len = SysStringLen(string); + tmp = SysAllocStringLen(string, string_len + delimiter_len); + memcpy(tmp + string_len, delimiter, delimiter_len * sizeof(WCHAR)); + SysFreeString(string); + string = tmp; + } + + string_len = SysStringLen(string); + str_len = SysStringLen(str); + tmp = SysAllocStringLen(string, string_len + str_len); + memcpy(tmp + string_len, str, str_len * sizeof(WCHAR)); + SysFreeString(string); + string = tmp; + + if (conv_str) { + SysFreeString(conv_str); + conv_str = NULL; + } + } + + SafeArrayUnaccessData(sa); + + if (args_cnt == 2) + if(V_VT(args+1) != VT_BSTR) + SysFreeString(delimiter); + + return return_bstr(res, string); }
static HRESULT Global_Split(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index dfa2816bec5..70f6a23c569 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -22,6 +22,28 @@ Dim x Class EmptyClass End Class
+' Helper function to print a variable +Function ToString(x) + If IsEmpty(x) Then + ToString = "Empty" + ElseIf IsNull(x) Then + ToString = "Null" + ElseIf IsObject(x) Then + ToString = "Object" + ElseIf IsArray(x) Then + Dim i, arrStr + arrStr = "Array(" + For i = LBound(x) To UBound(x) + arrStr = arrStr & ToString(x(i)) + If i < UBound(x) Then arrStr = arrStr & ", " + Next + arrStr = arrStr & ")" + ToString = arrStr + Else + ToString = CStr(x) + End If +End Function + Call ok(vbSunday = 1, "vbSunday = " & vbSunday) Call ok(getVT(vbSunday) = "VT_I2", "getVT(vbSunday) = " & getVT(vbSunday)) Call ok(vbMonday = 2, "vbMonday = " & vbMonday) @@ -713,6 +735,59 @@ TestLCase 0.123, doubleAsString(0.123) TestLCase Empty, "" Call ok(getVT(LCase(Null)) = "VT_NULL", "getVT(LCase(Null)) = " & getVT(LCase(Null)))
+' Join + +Sub TestJoin(arg, ex) + x = Join(arg) + Call ok(x = ex, "Join(" & ToString(arg) & ") = " & x & " expected " & ex) +End Sub + +Sub TestJoin2(arg1, arg2, ex) + x = Join(arg1, arg2) + Call ok(x = ex, "Join(" & ToString(arg1) & "," & arg2 & ") = " & x & " expected " & ex) +End Sub + +Sub TestJoinError(arg, num) + On Error Resume Next + Call Join(arg) + Dim err_num: err_num = Err.number + Call Err.clear() + On Error GoTo 0 + Call ok(err_num = num, "Join(" & ToString(arg) & ") expected Err.number = " & num & " got " & err_num) +End Sub + +TestJoin Array(), "" +TestJoin Array("a", "b", "c"), "a b c" +TestJoin Array("a", "b", "c", 1, 2, 3), "a b c 1 2 3" +TestJoin Array(1, Empty), "1 " + +TestJoin2 Array(), "", "" +TestJoin2 Array("a"), "-", "a" +TestJoin2 Array("a", "b"), "-", "a-b" +TestJoin2 Array("a", "b", "c"), "", "abc" +TestJoin2 Array(1, "Hello"), "-", "1-Hello" +TestJoin2 Array("a", "b", "c"), Empty, "abc" + +TestJoinError Null , 94 +TestJoinError Empty, 13 +TestJoinError 1, 13 +TestJoinError "test", 13 +TestJoinError 1.2, 13 +TestJoinError New EmptyClass, 438 +TestJoinError Array(1, Null), 13 + +On Error Resume Next +Call Join(Array(), Null) +Call ok(Err.number = 94, "Join(Array(), Null) expected Err.number = 94 got " & Err.number) +Call Err.clear +On Error GoTo 0 + +On Error Resume Next +Call Join(Array(), "a", "b") +Call ok(Err.number = 450, "Join(Array(), ""a"", ""b"") expected Err.number = 450 got " & Err.number) +Call Err.clear +On Error GoTo 0 + x=Split("abc") Call ok(x(0) = "abc", "Split(""abc"")(0)=" & x(0)) x = Split("abc def")
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150813
Your paranoid android.
=== debian11b (64 bit WoW report) ===
mshtml: xmlhttprequest.c:460: Test failed: AllResponseHeaders(L"Date: Thu, 09 Jan 2025 08:50:59 GMT\r\nContent-Type: application/xml\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nLast-Modified: Tue, 14 Jun 2022 15:45:18 GMT\r\nETag: W/"33-5e16a4aa23f18"\r\nCF-Cache-Status: DYNAMIC\r\nReport-To: {"endpoints":[{"url":"https:\/\/a.n"...) don't have expected substr(L"Content-Length: 51") xmlhttprequest.c:460: Test failed: AllResponseHeaders(L"Date: Thu, 09 Jan 2025 08:51:00 GMT\r\nContent-Type: application/xml\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nLast-Modified: Tue, 14 Jun 2022 15:45:18 GMT\r\nETag: W/"33-5e16a4aa23f18"\r\nCF-Cache-Status: DYNAMIC\r\nReport-To: {"endpoints":[{"url":"https:\/\/a.n"...) don't have expected substr(L"Content-Length: 51")
winhttp: notification.c:734: Test failed: got unexpected thread 0x11f8, err 0 winhttp.c:1205: Test failed: available_size = 546
wmp: media: Timeout