Jacek Caban : vbscript: Support reporting error location to script host.

Alexandre Julliard julliard at winehq.org
Thu Jan 23 15:48:48 CST 2020


Module: wine
Branch: master
Commit: e35564b36df5a0f1c5a141f28fb86e8b4c2495b3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e35564b36df5a0f1c5a141f28fb86e8b4c2495b3

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Jan 22 23:28:01 2020 +0100

vbscript: Support reporting error location to script host.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/vbscript/compile.c   | 17 ++++++++++-------
 dlls/vbscript/interp.c    | 20 +++++++++++++++++---
 dlls/vbscript/tests/run.c |  3 +--
 dlls/vbscript/vbscript.c  | 24 +++++++++++++++++++-----
 dlls/vbscript/vbscript.h  |  4 +++-
 5 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 1f9462aee8..e52d8b1a24 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 66ad206837..9c07535517 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 696c3f530b..015f2b816a 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 12681672ca..2b691af583 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 51797fbdfc..33ecb45bf4 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;
 




More information about the wine-cvs mailing list