[PATCH v5 0/1] MR10396: Draft: vbscript: Implement IActiveScriptError::GetSourceLineText.
Store a reference to vbscode_t in VBScriptError and compute the source line text on demand in GetSourceLineText. Also fix a memory leak in VBScriptError_Release by using clear_ei to free EXCEPINFO BSTRs. -- v5: vbscript: Implement IActiveScriptError::GetSourceLineText. https://gitlab.winehq.org/wine/wine/-/merge_requests/10396
From: Francis De Brabandere <francisdb@gmail.com> Store a reference to vbscode_t in VBScriptError and compute the source line text on demand in GetSourceLineText. Also fix a memory leak in VBScriptError_Release by using clear_ei to free EXCEPINFO BSTRs. --- dlls/vbscript/tests/run.c | 75 ++++++++++++++++++++++++++++----------- dlls/vbscript/vbscript.c | 37 ++++++++++++++++--- dlls/vbscript/vbscript.h | 2 +- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 4b69bc18ffa..8e40bb6cbce 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2007,6 +2007,8 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, S static IActiveScriptError **store_script_error; static ULONG error_line; static LONG error_char; +static BSTR error_source_line; +static HRESULT error_source_line_hres; static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) { @@ -2015,6 +2017,10 @@ static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, I hres = IActiveScriptError_GetSourcePosition(pscripterror, NULL, &error_line, &error_char); ok(hres == S_OK, "GetSourcePosition failed: %08lx\n", hres); + SysFreeString(error_source_line); + error_source_line = NULL; + error_source_line_hres = IActiveScriptError_GetSourceLineText(pscripterror, &error_source_line); + if(!expect_OnScriptError) { EXCEPINFO info; @@ -2696,6 +2702,7 @@ static void test_parse_errors(void) const WCHAR *src; unsigned error_line; int error_char; + const WCHAR *source_line; } invalid_scripts[] = { @@ -2703,7 +2710,8 @@ static void test_parse_errors(void) /* If...End If */ L"If 0 > 1 Then\n" " x = 0 End If\n", - 1, 10 + 1, 10, + L" x = 0 End If" }, { /* ElseIf...End If */ @@ -2711,50 +2719,58 @@ static void test_parse_errors(void) " x = 0\n" "ElseIf True Then\n" " x = 1 End If\n", - 3, 10 + 3, 10, + L" x = 1 End If" }, { /* Else End If (no separator) */ L"If False Then\n" " x = 0\n" "Else End If\n", - 2, 5 + 2, 5, + L"Else End If" }, { /* While...End While */ L"While False\n" " x = 0 End While\n", - 1, 10 + 1, 10, + L" x = 0 End While" }, { /* While...Wend */ L"While False\n" " x = 0 Wend\n", - 1, 10 + 1, 10, + L" x = 0 Wend" }, { /* Do While...Loop */ L"Do While False\n" " x = 0 Loop\n", - 1, 10 + 1, 10, + L" x = 0 Loop" }, { /* Do Until...Loop */ L"Do Until True\n" " x = 0 Loop\n", - 1, 10 + 1, 10, + L" x = 0 Loop" }, { /* Do...Loop While */ L"Do\n" " x = 0 Loop While False\n", - 1, 10 + 1, 10, + L" x = 0 Loop While False" }, { /* Do...Loop Until */ L"Do\n" " x = 0 Loop Until True\n", - 1, 10 + 1, 10, + L" x = 0 Loop Until True" }, { /* Select...End Select */ @@ -2765,36 +2781,43 @@ static void test_parse_errors(void) " Case 42\n" " x = True End Select\n" "Call ok(x, \"wrong case\")\n", - 5, 17 + 5, 17, + L" x = True End Select" }, { /* Class...End Class (empty) */ L"Class C End Class", - 0, 8 + 0, 8, + L"Class C End Class" }, { /* Class...End Class (empty) */ L"Class C _\nEnd Class", - 1, 0 + 1, 0, + L"End Class" }, { /* invalid use of parentheses for call statement */ L"strcomp(\"x\", \"y\")", - 0, -17 + 0, -17, + L"strcomp(\"x\", \"y\")" }, { L"\n\n\n cint _\n throwInt(&h80001234&)", - 3, 2 + 3, 2, + L" cint _" }, { L"dim x\n" "if true then throwInt(&h80001234&)", - 1, 13 + 1, 13, + L"if true then throwInt(&h80001234&)" }, { L"dim x\n" "if x = throwInt(&h80001234&) then x = 1", - 1, 0 + 1, 0, + L"if x = throwInt(&h80001234&) then x = 1" }, { L"sub test\n" @@ -2802,14 +2825,16 @@ static void test_parse_errors(void) " if x = throwInt(&h80001234&) then x = 1\n" "end sub\n" "test\n", - 2, 4 + 2, 4, + L" if x = throwInt(&h80001234&) then x = 1" }, { L"dim x\n" "do\n" " x = 1\n" "loop until throwInt(&h80001234&)\n", - 3, 0 + 3, 0, + L"loop until throwInt(&h80001234&)" }, { L"\n select case 3\n" @@ -2818,7 +2843,8 @@ static void test_parse_errors(void) " case throwInt(&h80001234&)\n" " throwInt &h87001234&\n" "end select\n", - 1, 2 + 1, 2, + L" select case 3" }, { L"if false then\n" @@ -2828,7 +2854,8 @@ static void test_parse_errors(void) "else\n" " throwInt &h87001234&\n" "end if\n", - 2, 1 + 2, 1, + L" elseif throwInt(&h80001234&) then" } }; HRESULT hres; @@ -2850,7 +2877,15 @@ static void test_parse_errors(void) todo_wine_if(invalid_scripts[i].error_char < 0) ok(error_char == abs(invalid_scripts[i].error_char), "[%u] error char %ld expected %d\n", i, error_char, invalid_scripts[i].error_char); + ok(error_source_line_hres == S_OK, "[%u] GetSourceLineText returned: %08lx\n", + i, error_source_line_hres); + if(error_source_line_hres == S_OK) + ok(!wcscmp(error_source_line, invalid_scripts[i].source_line), + "[%u] source line %s expected %s\n", i, + wine_dbgstr_w(error_source_line), wine_dbgstr_w(invalid_scripts[i].source_line)); } + SysFreeString(error_source_line); + error_source_line = NULL; } static void test_msgbox(void) diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 715c98d32bb..0a84b599d97 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -64,6 +64,8 @@ typedef struct { DWORD_PTR cookie; unsigned line; unsigned character; + vbscode_t *code; + unsigned loc; } VBScriptError; static inline WCHAR *heap_pool_strdup(heap_pool_t *heap, const WCHAR *str) @@ -505,8 +507,11 @@ static ULONG WINAPI VBScriptError_Release(IActiveScriptError *iface) TRACE("(%p) ref=%ld\n", This, ref); - if(!ref) + if(!ref) { + clear_ei(&This->ei); + release_vbscode(This->code); free(This); + } return ref; } @@ -542,8 +547,28 @@ static HRESULT WINAPI VBScriptError_GetSourcePosition(IActiveScriptError *iface, static HRESULT WINAPI VBScriptError_GetSourceLineText(IActiveScriptError *iface, BSTR *source) { VBScriptError *This = impl_from_IActiveScriptError(iface); - FIXME("(%p)->(%p)\n", This, source); - return E_NOTIMPL; + const WCHAR *nl, *line_end; + + TRACE("(%p)->(%p)\n", This, source); + + if(!source) + return E_POINTER; + + if(!This->code) { + *source = NULL; + return E_FAIL; + } + + nl = This->code->source + This->loc; + while(nl > This->code->source && nl[-1] != '\n') + nl--; + + line_end = This->code->source + This->loc; + while(*line_end && *line_end != '\n' && *line_end != '\r') + line_end++; + + *source = SysAllocStringLen(nl, line_end - nl); + return *source ? S_OK : E_OUTOFMEMORY; } static const IActiveScriptErrorVtbl VBScriptErrorVtbl = { @@ -555,7 +580,7 @@ static const IActiveScriptErrorVtbl VBScriptErrorVtbl = { VBScriptError_GetSourceLineText }; -HRESULT report_script_error(script_ctx_t *ctx, const vbscode_t *code, unsigned loc) +HRESULT report_script_error(script_ctx_t *ctx, vbscode_t *code, unsigned loc) { VBScriptError *error; const WCHAR *p, *nl; @@ -580,6 +605,10 @@ HRESULT report_script_error(script_ctx_t *ctx, const vbscode_t *code, unsigned l } error->character = code->source + loc - nl; + grab_vbscode(code); + error->code = code; + error->loc = loc; + hres = IActiveScriptSite_OnScriptError(ctx->site, &error->IActiveScriptError_iface); IActiveScriptError_Release(&error->IActiveScriptError_iface); return hres == S_OK ? SCRIPT_E_REPORTED : result; diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 6b67c8b1bc5..e1b3064c3a9 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -394,7 +394,7 @@ void release_dynamic_var(dynamic_var_t*); named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned); void release_named_item(named_item_t*); void clear_ei(EXCEPINFO*); -HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned); +HRESULT report_script_error(script_ctx_t*,vbscode_t*,unsigned); void detach_global_objects(script_ctx_t*); HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*); HRESULT array_access(SAFEARRAY *array, DISPPARAMS *dp, VARIANT **ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10396
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)