jscript: Suport generic error object for exception with no associated JavaScript exception value.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Jacek Caban 2020-01-31 17:22:42 +01:00 committed by Alexandre Julliard
parent a0e4dbcfd5
commit f6c5da47f7
5 changed files with 125 additions and 7 deletions

View File

@ -2753,8 +2753,8 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0};
WARN("Exception %08x %s", exception_hres, debugstr_jsval(ei->valid_value ? ei->value : jsval_undefined()));
if(ei->valid_value && jsval_type(ctx->ei->value) == JSV_OBJECT) {
error_obj = to_jsdisp(get_object(ctx->ei->value));
if(ei->valid_value && jsval_type(ei->value) == JSV_OBJECT) {
error_obj = to_jsdisp(get_object(ei->value));
if(error_obj) {
hres = jsdisp_propget_name(error_obj, messageW, &msg);
if(SUCCEEDED(hres)) {
@ -2768,6 +2768,9 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
print_backtrace(ctx);
}
if(exception_hres != DISP_E_EXCEPTION)
ei->error = exception_hres;
for(frame = ctx->call_ctx; !frame->except_frame; frame = ctx->call_ctx) {
DWORD flags;
@ -2779,7 +2782,7 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
flags = frame->flags;
pop_call_frame(ctx);
if(!(flags & EXEC_RETURN_TO_INTERP))
return exception_hres;
return DISP_E_EXCEPTION;
}
except_frame = frame->except_frame;
@ -2792,13 +2795,16 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
scope_pop(&frame->scope);
frame->ip = catch_off ? catch_off : except_frame->finally_off;
if(catch_off) assert(frame->bytecode->instrs[frame->ip].op == OP_enter_catch);
assert(!catch_off || frame->bytecode->instrs[frame->ip].op == OP_enter_catch);
if(ei->valid_value) {
except_val = ctx->ei->value;
ctx->ei->valid_value = FALSE;
ei->valid_value = FALSE;
}else {
except_val = jsval_undefined();
jsdisp_t *err;
if(!(err = create_builtin_error(ctx)))
return E_OUTOFMEMORY;
except_val = jsval_obj(err);
}
/* keep current except_frame if we're entering catch block with finally block associated */

View File

@ -18,6 +18,7 @@
#include <math.h>
#include <assert.h>
#include "jscript.h"
#include "engine.h"
@ -444,3 +445,82 @@ HRESULT throw_uri_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
return throw_error(ctx, error, str, ctx->uri_error_constr);
}
jsdisp_t *create_builtin_error(script_ctx_t *ctx)
{
jsdisp_t *constr = ctx->error_constr, *r;
jsexcept_t *ei = ctx->ei;
HRESULT hres;
assert(FAILED(ei->error) && ei->error != DISP_E_EXCEPTION);
if(is_jscript_error(ei->error)) {
switch(ei->error) {
case JS_E_SYNTAX:
case JS_E_MISSING_SEMICOLON:
case JS_E_MISSING_LBRACKET:
case JS_E_MISSING_RBRACKET:
case JS_E_EXPECTED_IDENTIFIER:
case JS_E_EXPECTED_ASSIGN:
case JS_E_INVALID_CHAR:
case JS_E_UNTERMINATED_STRING:
case JS_E_MISPLACED_RETURN:
case JS_E_INVALID_BREAK:
case JS_E_INVALID_CONTINUE:
case JS_E_LABEL_REDEFINED:
case JS_E_LABEL_NOT_FOUND:
case JS_E_EXPECTED_CCEND:
case JS_E_DISABLED_CC:
case JS_E_EXPECTED_AT:
constr = ctx->syntax_error_constr;
break;
case JS_E_TO_PRIMITIVE:
case JS_E_INVALIDARG:
case JS_E_OBJECT_REQUIRED:
case JS_E_INVALID_PROPERTY:
case JS_E_INVALID_ACTION:
case JS_E_MISSING_ARG:
case JS_E_FUNCTION_EXPECTED:
case JS_E_DATE_EXPECTED:
case JS_E_NUMBER_EXPECTED:
case JS_E_OBJECT_EXPECTED:
case JS_E_UNDEFINED_VARIABLE:
case JS_E_BOOLEAN_EXPECTED:
case JS_E_VBARRAY_EXPECTED:
case JS_E_INVALID_DELETE:
case JS_E_JSCRIPT_EXPECTED:
case JS_E_ENUMERATOR_EXPECTED:
case JS_E_ARRAY_EXPECTED:
case JS_E_NONCONFIGURABLE_REDEFINED:
case JS_E_NONWRITABLE_MODIFIED:
case JS_E_PROP_DESC_MISMATCH:
case JS_E_INVALID_WRITABLE_PROP_DESC:
constr = ctx->type_error_constr;
break;
case JS_E_SUBSCRIPT_OUT_OF_RANGE:
case JS_E_FRACTION_DIGITS_OUT_OF_RANGE:
case JS_E_PRECISION_OUT_OF_RANGE:
case JS_E_INVALID_LENGTH:
constr = ctx->range_error_constr;
break;
case JS_E_ILLEGAL_ASSIGN:
constr = ctx->reference_error_constr;
break;
case JS_E_REGEXP_SYNTAX:
constr = ctx->regexp_error_constr;
break;
case JS_E_INVALID_URI_CODING:
case JS_E_INVALID_URI_CHAR:
constr = ctx->uri_error_constr;
break;
}
}
hres = create_error(ctx, constr, ei->error, jsstr_empty(), &r);
return SUCCEEDED(hres) ? r : NULL;
}

View File

@ -207,7 +207,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a
hres = compile_script(ctx, src, 0, 0, NULL, NULL, TRUE, FALSE, &code);
if(FAILED(hres)) {
WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres);
return throw_syntax_error(ctx, hres, NULL);
return hres;
}
if(!frame || (frame->flags & EXEC_GLOBAL))

View File

@ -320,6 +320,7 @@ HRESULT throw_regexp_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
HRESULT throw_syntax_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
HRESULT throw_type_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
HRESULT throw_uri_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
jsdisp_t *create_builtin_error(script_ctx_t *ctx) DECLSPEC_HIDDEN;
HRESULT create_object(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
HRESULT create_math(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN;

View File

@ -1186,6 +1186,37 @@ case 3:
expect(ret, "try");
})();
(function() {
var e;
var E_FAIL = -2147467259;
var JS_E_SUBSCRIPT_OUT_OF_RANGE = -2146828279;
try {
throwInt(E_FAIL);
}catch(ex) {
e = ex;
}
ok(e.name === "Error", "e.name = " + e.name);
ok(e.message === "", "e.message = " + e.message);
ok(e.number === E_FAIL, "e.number = " + e.number);
try {
throwInt(JS_E_SUBSCRIPT_OUT_OF_RANGE);
}catch(ex) {
e = ex;
}
ok(e.name === "RangeError", "e.name = " + e.name);
ok(e.number === JS_E_SUBSCRIPT_OUT_OF_RANGE, "e.number = " + e.number);
try {
throwEI(JS_E_SUBSCRIPT_OUT_OF_RANGE);
}catch(ex) {
e = ex;
}
ok(e.name === "RangeError", "e.name = " + e.name);
ok(e.number === JS_E_SUBSCRIPT_OUT_OF_RANGE, "e.number = " + e.number);
})();
tmp = eval("1");
ok(tmp === 1, "eval(\"1\") !== 1");
eval("{ ok(tmp === 1, 'eval: tmp !== 1'); } tmp = 2;");