vbscript: Support reporting error location to script host.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eb73571fe9
commit
e35564b36d
|
@ -374,7 +374,7 @@ static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off)
|
||||||
return emit_catch_jmp(ctx, off, ctx->instr_cnt);
|
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)
|
if(error == SCRIPT_E_REPORTED)
|
||||||
return error;
|
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.scode = error = map_hres(error);
|
||||||
ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
|
ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
|
||||||
ctx->ei.bstrDescription = get_vbscript_error_string(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)
|
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(FAILED(hres)) {
|
||||||
if(ctx.parser.error_loc != -1)
|
if(ctx.parser.error_loc != -1)
|
||||||
ctx.loc = ctx.parser.error_loc;
|
ctx.loc = ctx.parser.error_loc;
|
||||||
hres = compile_error(script, hres);
|
hres = compile_error(script, &ctx, hres);
|
||||||
release_vbscode(code);
|
release_vbscode(code);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
|
hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
hres = compile_error(script, hres);
|
hres = compile_error(script, &ctx, hres);
|
||||||
release_compiler(&ctx);
|
release_compiler(&ctx);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code->option_explicit = ctx.parser.option_explicit;
|
||||||
ctx.global_consts = ctx.const_decls;
|
ctx.global_consts = ctx.const_decls;
|
||||||
code->option_explicit = ctx.parser.option_explicit;
|
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) {
|
for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
|
||||||
hres = create_function(&ctx, func_decl, &new_func);
|
hres = create_function(&ctx, func_decl, &new_func);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
hres = compile_error(script, hres);
|
hres = compile_error(script, &ctx, hres);
|
||||||
release_compiler(&ctx);
|
release_compiler(&ctx);
|
||||||
return hres;
|
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) {
|
for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
|
||||||
hres = compile_class(&ctx, class_decl);
|
hres = compile_class(&ctx, class_decl);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
|
hres = compile_error(script, &ctx, hres);
|
||||||
release_compiler(&ctx);
|
release_compiler(&ctx);
|
||||||
return compile_error(script, hres);
|
return hres;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = check_script_collisions(&ctx, script);
|
hres = check_script_collisions(&ctx, script);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
|
hres = compile_error(script, &ctx, hres);
|
||||||
release_compiler(&ctx);
|
release_compiler(&ctx);
|
||||||
return compile_error(script, hres);
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0;
|
code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0;
|
||||||
|
|
|
@ -275,6 +275,14 @@ void clear_ei(EXCEPINFO *ei)
|
||||||
memset(ei, 0, sizeof(*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)
|
static inline VARIANT *stack_pop(exec_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
assert(ctx->top);
|
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);
|
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;
|
stack_off = exec.instr->arg2.uint;
|
||||||
instr_jmp(&exec, exec.instr->arg1.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;
|
continue;
|
||||||
}else {
|
}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);
|
stack_popn(&exec, exec.top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2426,12 +2439,13 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd
|
||||||
assert(!exec.top);
|
assert(!exec.top);
|
||||||
|
|
||||||
if(extern_caller) {
|
if(extern_caller) {
|
||||||
IActiveScriptSite_OnLeaveScript(ctx->site);
|
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
if(!ctx->ei.scode)
|
if(!ctx->ei.scode)
|
||||||
ctx->ei.scode = hres;
|
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) {
|
if(SUCCEEDED(hres) && res) {
|
||||||
|
|
|
@ -2530,10 +2530,9 @@ static void test_parse_errors(void)
|
||||||
ok(hres == SCRIPT_E_REPORTED, "[%u] script returned: %08x\n", i, hres);
|
ok(hres == SCRIPT_E_REPORTED, "[%u] script returned: %08x\n", i, hres);
|
||||||
CHECK_CALLED(OnScriptError);
|
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",
|
ok(error_line == invalid_scripts[i].error_line, "[%u] error line %u expected %u\n",
|
||||||
i, error_line, invalid_scripts[i].error_line);
|
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",
|
ok(error_char == abs(invalid_scripts[i].error_char), "[%u] error char %d expected %d\n",
|
||||||
i, error_char, invalid_scripts[i].error_char);
|
i, error_char, invalid_scripts[i].error_char);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,9 @@ typedef struct {
|
||||||
IActiveScriptError IActiveScriptError_iface;
|
IActiveScriptError IActiveScriptError_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
EXCEPINFO ei;
|
EXCEPINFO ei;
|
||||||
|
DWORD_PTR cookie;
|
||||||
|
unsigned line;
|
||||||
|
unsigned character;
|
||||||
} VBScriptError;
|
} VBScriptError;
|
||||||
|
|
||||||
static inline WCHAR *heap_pool_strdup(heap_pool_t *heap, const WCHAR *str)
|
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);
|
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)
|
if(source_context)
|
||||||
*source_context = 0;
|
*source_context = This->cookie;
|
||||||
if(line)
|
if(line)
|
||||||
*line = 0;
|
*line = This->line;
|
||||||
if(character)
|
if(character)
|
||||||
*character = 0;
|
*character = This->character;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,9 +407,10 @@ static const IActiveScriptErrorVtbl VBScriptErrorVtbl = {
|
||||||
VBScriptError_GetSourceLineText
|
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;
|
VBScriptError *error;
|
||||||
|
const WCHAR *p, *nl;
|
||||||
HRESULT hres, result;
|
HRESULT hres, result;
|
||||||
|
|
||||||
if(!(error = heap_alloc(sizeof(*error))))
|
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));
|
memset(&ctx->ei, 0, sizeof(ctx->ei));
|
||||||
result = error->ei.scode;
|
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);
|
hres = IActiveScriptSite_OnScriptError(ctx->site, &error->IActiveScriptError_iface);
|
||||||
IActiveScriptError_Release(&error->IActiveScriptError_iface);
|
IActiveScriptError_Release(&error->IActiveScriptError_iface);
|
||||||
return hres == S_OK ? SCRIPT_E_REPORTED : result;
|
return hres == S_OK ? SCRIPT_E_REPORTED : result;
|
||||||
|
|
|
@ -192,6 +192,8 @@ struct _script_ctx_t {
|
||||||
BuiltinDisp *err_obj;
|
BuiltinDisp *err_obj;
|
||||||
|
|
||||||
EXCEPINFO ei;
|
EXCEPINFO ei;
|
||||||
|
vbscode_t *error_loc_code;
|
||||||
|
unsigned error_loc_offset;
|
||||||
|
|
||||||
struct list objects;
|
struct list objects;
|
||||||
struct list code_list;
|
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;
|
void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN;
|
||||||
IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
|
IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
|
||||||
void clear_ei(EXCEPINFO*) 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;
|
void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
|
||||||
HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;
|
HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue