diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 2be5f24fae8..61db10cd410 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -2521,7 +2521,7 @@ HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, UINT64 source_conte if(FAILED(hres)) { if(hres != DISP_E_EXCEPTION) throw_error(ctx, hres, NULL); - set_error_location(ctx->ei, compiler.code, compiler.loc, IDS_COMPILATION_ERROR); + set_error_location(ctx->ei, compiler.code, compiler.loc, IDS_COMPILATION_ERROR, NULL); release_bytecode(compiler.code); return DISP_E_EXCEPTION; } diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 054b0c7602c..f94cfd1e805 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -2779,7 +2779,7 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres) frame = ctx->call_ctx; if(exception_hres != DISP_E_EXCEPTION) throw_error(ctx, exception_hres, NULL); - set_error_location(ei, frame->bytecode, frame->bytecode->instrs[frame->ip].loc, IDS_RUNTIME_ERROR); + set_error_location(ei, frame->bytecode, frame->bytecode->instrs[frame->ip].loc, IDS_RUNTIME_ERROR, NULL); while(!frame->except_frame) { DWORD flags; diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index bb991c442ee..cad46e12c53 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -229,6 +229,7 @@ struct _jsexcept_t { jsstr_t *source; jsstr_t *message; + jsstr_t *line; bytecode_t *code; unsigned loc; @@ -240,7 +241,7 @@ struct _jsexcept_t { void enter_script(script_ctx_t*,jsexcept_t*) DECLSPEC_HIDDEN; HRESULT leave_script(script_ctx_t*,HRESULT) DECLSPEC_HIDDEN; void reset_ei(jsexcept_t*) DECLSPEC_HIDDEN; -void set_error_location(jsexcept_t*,bytecode_t*,unsigned,unsigned) DECLSPEC_HIDDEN; +void set_error_location(jsexcept_t*,bytecode_t*,unsigned,unsigned,jsstr_t*) DECLSPEC_HIDDEN; typedef struct _except_frame_t except_frame_t; struct _parser_ctx_t; diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index eca6c901388..4d54d74f6c2 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -420,7 +420,7 @@ HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) return DISP_E_EXCEPTION; } -void set_error_location(jsexcept_t *ei, bytecode_t *code, unsigned loc, unsigned source_id) +void set_error_location(jsexcept_t *ei, bytecode_t *code, unsigned loc, unsigned source_id, jsstr_t *line) { if(is_jscript_error(ei->error)) { if(!ei->source) { @@ -438,6 +438,8 @@ void set_error_location(jsexcept_t *ei, bytecode_t *code, unsigned loc, unsigned ei->code = bytecode_addref(code); ei->loc = loc; + if(line) + ei->line = jsstr_addref(line); } jsdisp_t *create_builtin_error(script_ctx_t *ctx) diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 860fb01cf51..8f97fa818d9 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -211,12 +211,17 @@ static HRESULT WINAPI JScriptError_GetSourceLineText(IActiveScriptError *iface, { JScriptError *This = impl_from_IActiveScriptError(iface); - FIXME("(%p)->(%p)\n", This, source); + TRACE("(%p)->(%p)\n", This, source); if(!source) return E_POINTER; - *source = NULL; - return E_FAIL; + + if(!This->ei.line) { + *source = NULL; + return E_FAIL; + } + + return jsstr_to_bstr(This->ei.line, source); } static const IActiveScriptErrorVtbl JScriptErrorVtbl = { @@ -248,6 +253,10 @@ void reset_ei(jsexcept_t *ei) jsstr_release(ei->message); ei->message = NULL; } + if(ei->line) { + jsstr_release(ei->line); + ei->line = NULL; + } } void enter_script(script_ctx_t *ctx, jsexcept_t *ei) diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 5a71a84ffac..507369ca202 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -1598,12 +1598,24 @@ HRESULT script_parse(script_ctx_t *ctx, struct _compiler_ctx_t *compiler, byteco heap_pool_clear(mark); hres = parser_ctx->hres; if(FAILED(hres)) { - WARN("parser failed around %s\n", - debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20)); + const WCHAR *line_start = code->source + parser_ctx->error_loc, *line_end = line_start; + jsstr_t *line_str; + + while(line_start > code->source && line_start[-1] != '\n') + line_start--; + while(*line_end && *line_end != '\n') + line_end++; + line_str = jsstr_alloc_len(line_start, line_end - line_start); + + WARN("parser failed around %s in line %s\n", + debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20), + debugstr_jsstr(line_str)); throw_error(ctx, hres, NULL); - set_error_location(ctx->ei, code, parser_ctx->error_loc, IDS_COMPILATION_ERROR); + set_error_location(ctx->ei, code, parser_ctx->error_loc, IDS_COMPILATION_ERROR, line_str); parser_release(parser_ctx); + if(line_str) + jsstr_release(line_str); return DISP_E_EXCEPTION; } diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 6e2250882d5..675bd819eee 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -2232,6 +2232,13 @@ static void test_error_reports(void) NULL, ERROR_TODO_SCODE | ERROR_TODO_DESCRIPTION }, + { + L"f(1\n,\n2,\n ,,3\n);\n", + JS_E_SYNTAX, 3, 1, + L"Microsoft JScript compilation error", + L"Syntax error", + L" ,,3" + }, }; if (!is_lang_english()) @@ -2304,9 +2311,7 @@ static void test_error_reports(void) hres = IActiveScriptError_GetSourceLineText(script_error, &line_text); if (tests[i].line_text) { - todo_wine ok(hres == S_OK, "GetSourceLineText failed: %08x\n", hres); - todo_wine ok(line_text != NULL && !lstrcmpW(line_text, tests[i].line_text), "[%u] GetSourceLineText returned %s expected %s\n", i, wine_dbgstr_w(line_text), wine_dbgstr_w(tests[i].line_text)); }