From: Francis De Brabandere <francisdb@gmail.com> Add error_code field to parse error tests, using negative values for codes that Wine does not yet return correctly (todo_wine), matching the existing pattern for error_char. --- dlls/vbscript/tests/run.c | 193 +++++++++++++++++++++++++++++++--- dlls/vbscript/vbscript.rc | 32 ++++++ dlls/vbscript/vbscript_defs.h | 32 ++++++ 3 files changed, 244 insertions(+), 13 deletions(-) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 1b46cd49393..eeae9e596a3 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2007,6 +2007,7 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, S static IActiveScriptError **store_script_error; static ULONG error_line; static LONG error_char; +static USHORT error_code; static BSTR error_source_line; static HRESULT error_source_line_hres; @@ -2029,6 +2030,15 @@ static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, I trace("Error in line %lu: %x %s\n", error_line + 1, info.wCode, wine_dbgstr_w(info.bstrDescription)); }else { IDispatchEx *dispex; + EXCEPINFO info; + + hres = IActiveScriptError_GetExceptionInfo(pscripterror, &info); + if(SUCCEEDED(hres)) { + error_code = HRESULT_CODE(info.scode); + SysFreeString(info.bstrSource); + SysFreeString(info.bstrDescription); + SysFreeString(info.bstrHelpFile); + } hres = IActiveScriptError_QueryInterface(pscripterror, &IID_IDispatchEx, (void**)&dispex); ok(hres == E_NOINTERFACE, "QI(IDispatchEx) returned: %08lx\n", hres); @@ -2704,6 +2714,7 @@ static void test_parse_errors(void) int error_char; const WCHAR *source_line; HRESULT source_line_hres; + int error_code; } invalid_scripts[] = { @@ -2712,7 +2723,7 @@ static void test_parse_errors(void) L"If 0 > 1 Then\n" " x = 0 End If\n", 1, 10, - L" x = 0 End If", S_OK + L" x = 0 End If", S_OK, -1042 }, { /* ElseIf...End If */ @@ -2721,7 +2732,7 @@ static void test_parse_errors(void) "ElseIf True Then\n" " x = 1 End If\n", 3, 10, - L" x = 1 End If", S_OK + L" x = 1 End If", S_OK, -1042 }, { /* Else End If (no separator) */ @@ -2729,49 +2740,49 @@ static void test_parse_errors(void) " x = 0\n" "Else End If\n", 2, 5, - L"Else End If", S_OK + L"Else End If", S_OK, -1024 }, { /* While...End While */ L"While False\n" " x = 0 End While\n", 1, 10, - L" x = 0 End While", S_OK + L" x = 0 End While", S_OK, -1024 }, { /* While...Wend */ L"While False\n" " x = 0 Wend\n", 1, 10, - L" x = 0 Wend", S_OK + L" x = 0 Wend", S_OK, -1025 }, { /* Do While...Loop */ L"Do While False\n" " x = 0 Loop\n", 1, 10, - L" x = 0 Loop", S_OK + L" x = 0 Loop", S_OK, -1025 }, { /* Do Until...Loop */ L"Do Until True\n" " x = 0 Loop\n", 1, 10, - L" x = 0 Loop", S_OK + L" x = 0 Loop", S_OK, -1025 }, { /* Do...Loop While */ L"Do\n" " x = 0 Loop While False\n", 1, 10, - L" x = 0 Loop While False", S_OK + L" x = 0 Loop While False", S_OK, -1025 }, { /* Do...Loop Until */ L"Do\n" " x = 0 Loop Until True\n", 1, 10, - L" x = 0 Loop Until True", S_OK + L" x = 0 Loop Until True", S_OK, -1025 }, { /* Select...End Select */ @@ -2783,25 +2794,25 @@ static void test_parse_errors(void) " x = True End Select\n" "Call ok(x, \"wrong case\")\n", 5, 17, - L" x = True End Select", S_OK + L" x = True End Select", S_OK, -1042 }, { /* Class...End Class (empty) */ L"Class C End Class", 0, 8, - L"Class C End Class", S_OK + L"Class C End Class", S_OK, -1024 }, { /* Class...End Class (empty) */ L"Class C _\nEnd Class", 1, 0, - L"End Class", S_OK + L"End Class", S_OK, -1024 }, { /* invalid use of parentheses for call statement */ L"strcomp(\"x\", \"y\")", 0, 17, - L"strcomp(\"x\", \"y\")", S_OK + L"strcomp(\"x\", \"y\")", S_OK, -1044 }, { L"\n\n\n cint _\n throwInt(&h80001234&)", @@ -2857,6 +2868,157 @@ static void test_parse_errors(void) "end if\n", 2, 1, NULL, E_FAIL + }, + { + /* Unterminated string constant - error 1033 */ + L"x = \"hello\n", + 0, -10, + NULL, S_OK, -1033 + }, + { + /* Expected 'End' - error 1014 */ + L"If True Then\nx = 1\n", + 2, 0, + NULL, S_OK, -1014 + }, + { + /* Name redefined - error 1041 */ + L"Dim a\nDim a\n", + 1, -4, + NULL, S_OK, -1041 + }, + { + /* Expected identifier - error 1010 */ + L"Dim If\n", + 0, 4, + NULL, S_OK, -1010 + }, + { + /* Invalid character - error 1032 */ + L"x = @invalid\n", + 0, 4, + NULL, S_OK, -1032 + }, + { + /* Expected literal constant - error 1045 */ + L"Const x = 1 + \"a\"\n", + 0, -17, + NULL, S_OK, -1045 + }, + { + /* Expected '(' - error 1005 */ + L"Sub x)\nEnd Sub\n", + 0, 5, + NULL, S_OK, -1005 + }, + { + /* Expected '=' - error 1011 */ + L"Const x\n", + 0, 7, + NULL, S_OK, -1011 + }, + { + /* Expected 'To' - error 1013 */ + L"For i = 1 x 10\nNext\n", + 0, 10, + NULL, S_OK, -1013 + }, + { + /* Expected 'Then' - error 1017 */ + L"If True\nEnd If\n", + 0, 7, + NULL, S_OK, -1017 + }, + { + /* Expected 'Wend' - error 1018 */ + L"While True\nx = 1\n", + 2, 0, + NULL, S_OK, -1018 + }, + { + /* Expected 'Loop' - error 1019 */ + L"Do\nx = 1\n", + 2, 0, + NULL, S_OK, -1019 + }, + { + /* Expected 'Next' - error 1020 */ + L"For i = 1 To 10\nx = 1\n", + 2, 0, + NULL, S_OK, -1020 + }, + { + /* Expected 'Case' - error 1021 */ + L"Select x\nEnd Select\n", + 0, 7, + NULL, S_OK, -1021 + }, + { + /* Expected integer constant - error 1026 */ + L"Dim x(\"a\")\n", + 0, 6, + NULL, S_OK, -1026 + }, + { + /* Invalid number - error 1031 */ + L"x = 1e999\n", + 0, -9, + NULL, S_OK, -1031 + }, + { + /* 'loop' without 'do' - error 1038 */ + L"Loop\n", + 0, 0, + NULL, S_OK, -1038 + }, + { + /* Invalid 'exit' statement - error 1039 */ + L"Exit Do\n", + 0, -5, + NULL, S_OK, -1039 + }, + { + /* Expected 'In' - error 1046 */ + L"For Each x = arr\nNext\n", + 0, 11, + NULL, S_OK, -1046 + }, + { + /* Must be defined inside a Class - error 1048 */ + L"Property Get x\nEnd Property\n", + 0, 9, + NULL, S_OK, -1048 + }, + { + /* Expected Let or Set or Get - error 1049 */ + L"Class C\nProperty x\nEnd Property\nEnd Class\n", + 1, 9, + NULL, S_OK, -1049 + }, + /* TODO: Wine allows arguments on Class_Initialize/Class_Terminate + { + Class initialize/terminate no arguments - error 1053 + L"Class C\nSub Class_Initialize(x)\nEnd Sub\nEnd Class\n", + 1, 20, 1053 + }, + */ + { + /* Property Let/Set needs at least one argument - error 1054 */ + L"Class C\nProperty Let x\nEnd Property\nEnd Class\n", + 1, 14, + NULL, S_OK, -1054 + }, + { + /* Unexpected 'Next' - error 1055 */ + L"Next\n", + 0, 0, + NULL, S_OK, -1055 + }, + { + /* 'Default' must also specify 'Public' - error 1057 */ + L"Class C\nDefault Private Function f()\nf = 1\nEnd Function\nEnd Class\n", + 1, 0, + NULL, S_OK, -1057 } }; HRESULT hres; @@ -2866,6 +3028,7 @@ static void test_parse_errors(void) { error_line = ~0; error_char = -1; + error_code = 0; onerror_hres = S_OK; SET_EXPECT(OnScriptError); @@ -2878,6 +3041,10 @@ 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); + if(invalid_scripts[i].error_code) + todo_wine_if(invalid_scripts[i].error_code < 0) + ok(error_code == abs(invalid_scripts[i].error_code), "[%u] error code %u expected %u\n", + i, error_code, abs(invalid_scripts[i].error_code)); ok(error_source_line_hres == invalid_scripts[i].source_line_hres, "[%u] GetSourceLineText returned: %08lx\n", i, error_source_line_hres); if(error_source_line_hres == S_OK && invalid_scripts[i].source_line) diff --git a/dlls/vbscript/vbscript.rc b/dlls/vbscript/vbscript.rc index b9a1c3ad5c3..a0f7381bcf0 100644 --- a/dlls/vbscript/vbscript.rc +++ b/dlls/vbscript/vbscript.rc @@ -59,6 +59,38 @@ STRINGTABLE VBSE_INVALID_TYPELIB_VARIABLE "Variable uses an Automation type not supported in VBScript" VBSE_SERVER_NOT_FOUND "The remote server machine does not exist or is unavailable" VBSE_UNQUALIFIED_REFERENCE "Invalid or unqualified reference" + VBSE_SYNTAX_ERROR "Syntax error" + VBSE_EXPECTED_LPAREN "Expected '('" + VBSE_EXPECTED_IDENTIFIER "Expected identifier" + VBSE_EXPECTED_ASSIGN "Expected '='" + VBSE_EXPECTED_TO "Expected 'To'" + VBSE_EXPECTED_END "Expected 'End'" + VBSE_EXPECTED_THEN "Expected 'Then'" + VBSE_EXPECTED_WEND "Expected 'Wend'" + VBSE_EXPECTED_LOOP "Expected 'Loop'" + VBSE_EXPECTED_NEXT "Expected 'Next'" + VBSE_EXPECTED_CASE "Expected 'Case'" + VBSE_EXPECTED_STATEMENT "Expected statement" + VBSE_EXPECTED_END_OF_STATEMENT "Expected end of statement" + VBSE_EXPECTED_INTEGER_CONSTANT "Expected integer constant" + VBSE_EXPECTED_WHILE_UNTIL_EOS "Expected 'While', 'Until' or end of statement" + VBSE_INVALID_NUMBER "Invalid number" + VBSE_INVALID_CHAR "Invalid character" + VBSE_UNTERMINATED_STRING "Unterminated string constant" + VBSE_LOOP_WITHOUT_DO "'loop' without 'do'" + VBSE_INVALID_EXIT "Invalid 'exit' statement" + VBSE_NAME_REDEFINED "Name redefined" + VBSE_MUST_BE_FIRST_STATEMENT "Must be first statement on the line" + VBSE_CANNOT_USE_PARENS_CALLING_SUB "Cannot use parentheses when calling a Sub" + VBSE_EXPECTED_LITERAL_CONSTANT "Expected literal constant" + VBSE_EXPECTED_IN "Expected 'In'" + VBSE_EXPECTED_CLASS "Expected 'Class'" + VBSE_MUST_BE_INSIDE_CLASS "Must be defined inside a Class" + VBSE_EXPECTED_LET_SET_GET "Expected Let or Set or Get in property declaration" + VBSE_CLASS_INIT_NO_ARGS "Class initialize or terminate do not have arguments" + VBSE_PROPERTY_LET_SET_NEEDS_ARG "Property set or let must have at least one argument" + VBSE_UNEXPECTED_NEXT "Unexpected 'Next'" + VBSE_DEFAULT_MUST_BE_PUBLIC "'Default' specification must also specify 'Public'" VBS_COMPILE_ERROR "Microsoft VBScript compilation error" VBS_RUNTIME_ERROR "Microsoft VBScript runtime error" diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h index e0e9d1cac94..06d3b8990fb 100644 --- a/dlls/vbscript/vbscript_defs.h +++ b/dlls/vbscript/vbscript_defs.h @@ -270,6 +270,38 @@ #define VBSE_INVALID_TYPELIB_VARIABLE 458 #define VBSE_SERVER_NOT_FOUND 462 #define VBSE_UNQUALIFIED_REFERENCE 505 +#define VBSE_SYNTAX_ERROR 1002 +#define VBSE_EXPECTED_LPAREN 1005 +#define VBSE_EXPECTED_IDENTIFIER 1010 +#define VBSE_EXPECTED_ASSIGN 1011 +#define VBSE_EXPECTED_TO 1013 +#define VBSE_EXPECTED_END 1014 +#define VBSE_EXPECTED_THEN 1017 +#define VBSE_EXPECTED_WEND 1018 +#define VBSE_EXPECTED_LOOP 1019 +#define VBSE_EXPECTED_NEXT 1020 +#define VBSE_EXPECTED_CASE 1021 +#define VBSE_EXPECTED_STATEMENT 1024 +#define VBSE_EXPECTED_END_OF_STATEMENT 1025 +#define VBSE_EXPECTED_INTEGER_CONSTANT 1026 +#define VBSE_EXPECTED_WHILE_UNTIL_EOS 1028 +#define VBSE_INVALID_NUMBER 1031 +#define VBSE_INVALID_CHAR 1032 +#define VBSE_UNTERMINATED_STRING 1033 +#define VBSE_LOOP_WITHOUT_DO 1038 +#define VBSE_INVALID_EXIT 1039 +#define VBSE_NAME_REDEFINED 1041 +#define VBSE_MUST_BE_FIRST_STATEMENT 1042 +#define VBSE_CANNOT_USE_PARENS_CALLING_SUB 1044 +#define VBSE_EXPECTED_LITERAL_CONSTANT 1045 +#define VBSE_EXPECTED_IN 1046 +#define VBSE_EXPECTED_CLASS 1047 +#define VBSE_MUST_BE_INSIDE_CLASS 1048 +#define VBSE_EXPECTED_LET_SET_GET 1049 +#define VBSE_CLASS_INIT_NO_ARGS 1053 +#define VBSE_PROPERTY_LET_SET_NEEDS_ARG 1054 +#define VBSE_UNEXPECTED_NEXT 1055 +#define VBSE_DEFAULT_MUST_BE_PUBLIC 1057 #define VBS_COMPILE_ERROR 4096 #define VBS_RUNTIME_ERROR 4097 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10386