diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 1f9462aee8b..e52d8b1a240 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -374,7 +374,7 @@ static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off) return emit_catch_jmp(ctx, off, ctx->instr_cnt); } -static HRESULT compile_error(script_ctx_t *ctx, HRESULT error) +static HRESULT compile_error(script_ctx_t *ctx, compile_ctx_t *compiler, HRESULT error) { if(error == SCRIPT_E_REPORTED) return error; @@ -383,7 +383,7 @@ static HRESULT compile_error(script_ctx_t *ctx, HRESULT error) ctx->ei.scode = error = map_hres(error); ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR); ctx->ei.bstrDescription = get_vbscript_error_string(error); - return report_script_error(ctx); + return report_script_error(ctx, compiler->code, compiler->loc); } static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global) @@ -1926,18 +1926,19 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli if(FAILED(hres)) { if(ctx.parser.error_loc != -1) ctx.loc = ctx.parser.error_loc; - hres = compile_error(script, hres); + hres = compile_error(script, &ctx, hres); release_vbscode(code); return hres; } hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code); if(FAILED(hres)) { - hres = compile_error(script, hres); + hres = compile_error(script, &ctx, hres); release_compiler(&ctx); return hres; } + code->option_explicit = ctx.parser.option_explicit; ctx.global_consts = ctx.const_decls; code->option_explicit = ctx.parser.option_explicit; @@ -1945,7 +1946,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) { hres = create_function(&ctx, func_decl, &new_func); if(FAILED(hres)) { - hres = compile_error(script, hres); + hres = compile_error(script, &ctx, hres); release_compiler(&ctx); return hres; } @@ -1957,15 +1958,17 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) { hres = compile_class(&ctx, class_decl); if(FAILED(hres)) { + hres = compile_error(script, &ctx, hres); release_compiler(&ctx); - return compile_error(script, hres); + return hres; } } hres = check_script_collisions(&ctx, script); if(FAILED(hres)) { + hres = compile_error(script, &ctx, hres); release_compiler(&ctx); - return compile_error(script, hres); + return hres; } code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0; diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 66ad2068375..9c075355174 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -275,6 +275,14 @@ void clear_ei(EXCEPINFO *ei) memset(ei, 0, sizeof(*ei)); } +static void clear_error_loc(script_ctx_t *ctx) +{ + if(ctx->error_loc_code) { + release_vbscode(ctx->error_loc_code); + ctx->error_loc_code = NULL; + } +} + static inline VARIANT *stack_pop(exec_ctx_t *ctx) { assert(ctx->top); @@ -2396,6 +2404,7 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd TRACE("unwind jmp %d stack_off %d\n", exec.instr->arg1.uint, exec.instr->arg2.uint); + clear_error_loc(ctx); stack_off = exec.instr->arg2.uint; instr_jmp(&exec, exec.instr->arg1.uint); @@ -2414,7 +2423,11 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd continue; }else { - WARN("Failed %08x\n", hres); + if(!ctx->error_loc_code) { + grab_vbscode(exec.code); + ctx->error_loc_code = exec.code; + ctx->error_loc_offset = exec.instr->loc; + } stack_popn(&exec, exec.top); break; } @@ -2426,12 +2439,13 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd assert(!exec.top); if(extern_caller) { - IActiveScriptSite_OnLeaveScript(ctx->site); if(FAILED(hres)) { if(!ctx->ei.scode) ctx->ei.scode = hres; - hres = report_script_error(ctx); + hres = report_script_error(ctx, ctx->error_loc_code, ctx->error_loc_offset); + clear_error_loc(ctx); } + IActiveScriptSite_OnLeaveScript(ctx->site); } if(SUCCEEDED(hres) && res) { diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 696c3f530bb..015f2b816ae 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2530,10 +2530,9 @@ static void test_parse_errors(void) ok(hres == SCRIPT_E_REPORTED, "[%u] script returned: %08x\n", i, hres); CHECK_CALLED(OnScriptError); - todo_wine_if(invalid_scripts[i].error_line) ok(error_line == invalid_scripts[i].error_line, "[%u] error line %u expected %u\n", i, error_line, invalid_scripts[i].error_line); - todo_wine_if(invalid_scripts[i].error_char) + todo_wine_if(invalid_scripts[i].error_char < 0) ok(error_char == abs(invalid_scripts[i].error_char), "[%u] error char %d expected %d\n", i, error_char, invalid_scripts[i].error_char); } diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 12681672caa..2b691af5833 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -61,6 +61,9 @@ typedef struct { IActiveScriptError IActiveScriptError_iface; LONG ref; EXCEPINFO ei; + DWORD_PTR cookie; + unsigned line; + unsigned character; } VBScriptError; static inline WCHAR *heap_pool_strdup(heap_pool_t *heap, const WCHAR *str) @@ -377,14 +380,14 @@ static HRESULT WINAPI VBScriptError_GetSourcePosition(IActiveScriptError *iface, { VBScriptError *This = impl_from_IActiveScriptError(iface); - FIXME("(%p)->(%p %p %p)\n", This, source_context, line, character); + TRACE("(%p)->(%p %p %p)\n", This, source_context, line, character); if(source_context) - *source_context = 0; + *source_context = This->cookie; if(line) - *line = 0; + *line = This->line; if(character) - *character = 0; + *character = This->character; return S_OK; } @@ -404,9 +407,10 @@ static const IActiveScriptErrorVtbl VBScriptErrorVtbl = { VBScriptError_GetSourceLineText }; -HRESULT report_script_error(script_ctx_t *ctx) +HRESULT report_script_error(script_ctx_t *ctx, const vbscode_t *code, unsigned loc) { VBScriptError *error; + const WCHAR *p, *nl; HRESULT hres, result; if(!(error = heap_alloc(sizeof(*error)))) @@ -418,6 +422,16 @@ HRESULT report_script_error(script_ctx_t *ctx) memset(&ctx->ei, 0, sizeof(ctx->ei)); result = error->ei.scode; + p = code->source; + error->cookie = code->cookie; + error->line = code->start_line; + for(nl = p = code->source; p < code->source + loc; p++) { + if(*p != '\n') continue; + error->line++; + nl = p + 1; + } + error->character = code->source + loc - nl; + 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 51797fbdfc0..33ecb45bf43 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -192,6 +192,8 @@ struct _script_ctx_t { BuiltinDisp *err_obj; EXCEPINFO ei; + vbscode_t *error_loc_code; + unsigned error_loc_offset; struct list objects; struct list code_list; @@ -372,7 +374,7 @@ HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN; IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN; -HRESULT report_script_error(script_ctx_t*) DECLSPEC_HIDDEN; +HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned) DECLSPEC_HIDDEN; void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN; HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;