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

Alexandre Julliard julliard at winehq.org
Sun Feb 2 12:56:45 CST 2020


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Jan 31 17:22:42 2020 +0100

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

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

---

 dlls/jscript/engine.c      | 18 +++++++----
 dlls/jscript/error.c       | 80 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/jscript/global.c      |  2 +-
 dlls/jscript/jscript.h     |  1 +
 dlls/jscript/tests/lang.js | 31 ++++++++++++++++++
 5 files changed, 125 insertions(+), 7 deletions(-)

diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index 8b121747fe..2fa171764b 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -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 */
diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c
index 66dbccfbc0..685fbd362f 100644
--- a/dlls/jscript/error.c
+++ b/dlls/jscript/error.c
@@ -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;
+}
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c
index bd1f45b940..2b5f3894ca 100644
--- a/dlls/jscript/global.c
+++ b/dlls/jscript/global.c
@@ -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))
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 1c85691edd..93c6f92bae 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -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;
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 4812a066d1..be0d0d2fa1 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -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;");




More information about the wine-cvs mailing list