jscript: Use separated jsexcept_t instance for each external call.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Jacek Caban 2020-01-30 15:50:15 +01:00 committed by Alexandre Julliard
parent 274503c839
commit 63683b42f7
8 changed files with 91 additions and 61 deletions

View File

@ -1512,6 +1512,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
{ {
jsdisp_t *This = impl_from_IDispatchEx(iface); jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *prop; dispex_prop_t *prop;
jsexcept_t ei;
HRESULT hres; HRESULT hres;
TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
@ -1525,7 +1526,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
return DISP_E_MEMBERNOTFOUND; return DISP_E_MEMBERNOTFOUND;
} }
clear_ei(This->ctx); enter_script(This->ctx, &ei);
switch(wFlags) { switch(wFlags) {
case DISPATCH_METHOD|DISPATCH_PROPERTYGET: case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
@ -1538,7 +1539,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
hres = convert_params(pdp, buf, &argc, &argv); hres = convert_params(pdp, buf, &argc, &argv);
if(FAILED(hres)) if(FAILED(hres))
return hres; break;
hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller);
if(argv != buf) if(argv != buf)
@ -1570,12 +1571,13 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
if(i == pdp->cNamedArgs) { if(i == pdp->cNamedArgs) {
TRACE("no value to set\n"); TRACE("no value to set\n");
return DISP_E_PARAMNOTOPTIONAL; hres = DISP_E_PARAMNOTOPTIONAL;
break;
} }
hres = variant_to_jsval(pdp->rgvarg+i, &val); hres = variant_to_jsval(pdp->rgvarg+i, &val);
if(FAILED(hres)) if(FAILED(hres))
return hres; break;
hres = prop_put(This, prop, val); hres = prop_put(This, prop, val);
jsval_release(val); jsval_release(val);
@ -1583,12 +1585,11 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
} }
default: default:
FIXME("Unimplemented flags %x\n", wFlags); FIXME("Unimplemented flags %x\n", wFlags);
return E_INVALIDARG; hres = E_INVALIDARG;
break;
} }
if(pei) return leave_script(This->ctx, hres);
*pei = This->ctx->ei.ei;
return hres;
} }
static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret)

View File

@ -418,13 +418,6 @@ static void scope_pop(scope_chain_t **scope)
scope_release(tmp); scope_release(tmp);
} }
void clear_ei(script_ctx_t *ctx)
{
memset(&ctx->ei.ei, 0, sizeof(ctx->ei.ei));
jsval_release(ctx->ei.val);
ctx->ei.val = jsval_undefined();
}
void scope_release(scope_chain_t *scope) void scope_release(scope_chain_t *scope)
{ {
if(--scope->ref) if(--scope->ref)
@ -867,8 +860,8 @@ static HRESULT interp_throw(script_ctx_t *ctx)
{ {
TRACE("\n"); TRACE("\n");
jsval_release(ctx->ei.val); jsval_release(ctx->ei->value);
ctx->ei.val = stack_pop(ctx); ctx->ei->value = stack_pop(ctx);
return DISP_E_EXCEPTION; return DISP_E_EXCEPTION;
} }
@ -964,7 +957,7 @@ static HRESULT interp_end_finally(script_ctx_t *ctx)
if(!get_bool(v)) { if(!get_bool(v)) {
TRACE("passing exception\n"); TRACE("passing exception\n");
ctx->ei.val = stack_pop(ctx); ctx->ei->value = stack_pop(ctx);
return DISP_E_EXCEPTION; return DISP_E_EXCEPTION;
} }
@ -2731,9 +2724,9 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0}; static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0};
WARN("Exception %08x %s", exception_hres, debugstr_jsval(ctx->ei.val)); WARN("Exception %08x %s", exception_hres, debugstr_jsval(ctx->ei->value));
if(jsval_type(ctx->ei.val) == JSV_OBJECT) { if(jsval_type(ctx->ei->value) == JSV_OBJECT) {
error_obj = to_jsdisp(get_object(ctx->ei.val)); error_obj = to_jsdisp(get_object(ctx->ei->value));
if(error_obj) { if(error_obj) {
hres = jsdisp_propget_name(error_obj, messageW, &msg); hres = jsdisp_propget_name(error_obj, messageW, &msg);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
@ -2773,9 +2766,8 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
frame->ip = catch_off ? catch_off : except_frame->finally_off; frame->ip = catch_off ? catch_off : except_frame->finally_off;
if(catch_off) assert(frame->bytecode->instrs[frame->ip].op == OP_enter_catch); if(catch_off) assert(frame->bytecode->instrs[frame->ip].op == OP_enter_catch);
except_val = ctx->ei.val; except_val = ctx->ei->value;
ctx->ei.val = jsval_undefined(); ctx->ei->value = jsval_undefined();
clear_ei(ctx);
/* keep current except_frame if we're entering catch block with finally block associated */ /* keep current except_frame if we're entering catch block with finally block associated */
if(catch_off && except_frame->finally_off) { if(catch_off && except_frame->finally_off) {

View File

@ -221,6 +221,15 @@ static inline scope_chain_t *scope_addref(scope_chain_t *scope)
return scope; return scope;
} }
struct _jsexcept_t {
jsval_t value;
jsexcept_t *prev;
};
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;
typedef struct _except_frame_t except_frame_t; typedef struct _except_frame_t except_frame_t;
struct _parser_ctx_t; struct _parser_ctx_t;

View File

@ -20,6 +20,7 @@
#include <math.h> #include <math.h>
#include "jscript.h" #include "jscript.h"
#include "engine.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -403,8 +404,8 @@ static HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str, j
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
jsval_release(ctx->ei.val); jsval_release(ctx->ei->value);
ctx->ei.val = jsval_obj(err); ctx->ei->value = jsval_obj(err);
return error; return error;
} }

View File

@ -70,7 +70,6 @@ void script_release(script_ctx_t *ctx)
return; return;
jsval_release(ctx->acc); jsval_release(ctx->acc);
clear_ei(ctx);
if(ctx->cc) if(ctx->cc)
release_cc(ctx->cc); release_cc(ctx->cc);
heap_pool_free(&ctx->tmp_heap); heap_pool_free(&ctx->tmp_heap);
@ -102,13 +101,39 @@ static inline BOOL is_started(script_ctx_t *ctx)
|| ctx->state == SCRIPTSTATE_DISCONNECTED; || ctx->state == SCRIPTSTATE_DISCONNECTED;
} }
void reset_ei(jsexcept_t *ei)
{
jsval_release(ei->value);
ei->value = jsval_undefined();
}
void enter_script(script_ctx_t *ctx, jsexcept_t *ei)
{
memset(ei, 0, sizeof(*ei));
ei->prev = ctx->ei;
ctx->ei = ei;
TRACE("ctx %p ei %p prev %p\n", ctx, ei, ei->prev);
}
HRESULT leave_script(script_ctx_t *ctx, HRESULT result)
{
jsexcept_t *ei = ctx->ei;
TRACE("ctx %p ei %p prev %p\n", ctx, ei, ei->prev);
ctx->ei = ei->prev;
if(FAILED(result))
WARN("%08x\n", result);
reset_ei(ei);
return result;
}
static HRESULT exec_global_code(JScript *This, bytecode_t *code) static HRESULT exec_global_code(JScript *This, bytecode_t *code)
{ {
HRESULT hres; HRESULT hres;
IActiveScriptSite_OnEnterScript(This->site); IActiveScriptSite_OnEnterScript(This->site);
clear_ei(This->ctx);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, NULL); hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, NULL);
IActiveScriptSite_OnLeaveScript(This->site); IActiveScriptSite_OnLeaveScript(This->site);
@ -141,9 +166,14 @@ static void clear_persistent_code_list(JScript *This)
static void exec_queued_code(JScript *This) static void exec_queued_code(JScript *This)
{ {
bytecode_t *iter; bytecode_t *iter;
jsexcept_t ei;
HRESULT hres;
LIST_FOR_EACH_ENTRY(iter, &This->queued_code, bytecode_t, entry) LIST_FOR_EACH_ENTRY(iter, &This->queued_code, bytecode_t, entry) {
exec_global_code(This, iter); enter_script(This->ctx, &ei);
hres = exec_global_code(This, iter);
leave_script(This->ctx, hres);
}
clear_script_queue(This); clear_script_queue(This);
} }
@ -723,7 +753,6 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
ctx->safeopt = This->safeopt; ctx->safeopt = This->safeopt;
ctx->version = This->version; ctx->version = This->version;
ctx->html_mode = This->html_mode; ctx->html_mode = This->html_mode;
ctx->ei.val = jsval_undefined();
ctx->acc = jsval_undefined(); ctx->acc = jsval_undefined();
heap_pool_init(&ctx->tmp_heap); heap_pool_init(&ctx->tmp_heap);
@ -765,6 +794,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
{ {
JScript *This = impl_from_IActiveScriptParse(iface); JScript *This = impl_from_IActiveScriptParse(iface);
bytecode_t *code; bytecode_t *code;
jsexcept_t ei;
HRESULT hres; HRESULT hres;
TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode), TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
@ -774,17 +804,17 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED; return E_UNEXPECTED;
enter_script(This->ctx, &ei);
hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLine, NULL, pstrDelimiter, hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLine, NULL, pstrDelimiter,
(dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, This->is_encode, &code); (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, This->is_encode, &code);
if(FAILED(hres)) if(FAILED(hres))
return hres; return leave_script(This->ctx, hres);
if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { if(dwFlags & SCRIPTTEXT_ISEXPRESSION) {
jsval_t r; jsval_t r;
IActiveScriptSite_OnEnterScript(This->site); IActiveScriptSite_OnEnterScript(This->site);
clear_ei(This->ctx);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, &r); hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, &r);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
if(pvarResult) if(pvarResult)
@ -793,7 +823,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
} }
IActiveScriptSite_OnLeaveScript(This->site); IActiveScriptSite_OnLeaveScript(This->site);
return hres; return leave_script(This->ctx, hres);
} }
code->is_persistent = (dwFlags & SCRIPTTEXT_ISPERSISTENT) != 0; code->is_persistent = (dwFlags & SCRIPTTEXT_ISPERSISTENT) != 0;
@ -804,17 +834,16 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
*/ */
if(!pvarResult && !is_started(This->ctx)) { if(!pvarResult && !is_started(This->ctx)) {
list_add_tail(&This->queued_code, &code->entry); list_add_tail(&This->queued_code, &code->entry);
return S_OK; }else {
hres = exec_global_code(This, code);
if(code->is_persistent)
list_add_tail(&This->persistent_code, &code->entry);
else
release_bytecode(code);
} }
hres = exec_global_code(This, code); if(FAILED(hres = leave_script(This->ctx, hres)))
if(code->is_persistent)
list_add_tail(&This->persistent_code, &code->entry);
else
release_bytecode(code);
if(FAILED(hres))
return hres; return hres;
if(pvarResult) if(pvarResult)
@ -862,6 +891,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
JScript *This = impl_from_IActiveScriptParseProcedure2(iface); JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
bytecode_t *code; bytecode_t *code;
jsdisp_t *dispex; jsdisp_t *dispex;
jsexcept_t ei;
HRESULT hres; HRESULT hres;
TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams), TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
@ -871,15 +901,13 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED; return E_UNEXPECTED;
enter_script(This->ctx, &ei);
hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLineNumber, pstrFormalParams, hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLineNumber, pstrFormalParams,
pstrDelimiter, FALSE, This->is_encode, &code); pstrDelimiter, FALSE, This->is_encode, &code);
if(FAILED(hres)) { if(SUCCEEDED(hres))
WARN("Parse failed %08x\n", hres); hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex);
return hres;
}
hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex);
release_bytecode(code); release_bytecode(code);
hres = leave_script(This->ctx, hres);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1051,17 +1079,20 @@ static ULONG WINAPI VariantChangeType_Release(IVariantChangeType *iface)
static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt) static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt)
{ {
JScript *This = impl_from_IVariantChangeType(iface); JScript *This = impl_from_IVariantChangeType(iface);
jsexcept_t ei;
VARIANT res; VARIANT res;
HRESULT hres; HRESULT hres;
TRACE("(%p)->(%p %p%s %x %d)\n", This, dst, src, debugstr_variant(src), lcid, vt); TRACE("(%p)->(%p %s %x %s)\n", This, dst, debugstr_variant(src), lcid, debugstr_vt(vt));
if(!This->ctx) { if(!This->ctx) {
FIXME("Object uninitialized\n"); FIXME("Object uninitialized\n");
return E_UNEXPECTED; return E_UNEXPECTED;
} }
enter_script(This->ctx, &ei);
hres = variant_change_type(This->ctx, &res, src, vt); hres = variant_change_type(This->ctx, &res, src, vt);
hres = leave_script(This->ctx, hres);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;

View File

@ -48,6 +48,7 @@
typedef struct _jsval_t jsval_t; typedef struct _jsval_t jsval_t;
typedef struct _jsstr_t jsstr_t; typedef struct _jsstr_t jsstr_t;
typedef struct _jsexcept_t jsexcept_t;
typedef struct _script_ctx_t script_ctx_t; typedef struct _script_ctx_t script_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t; typedef struct _dispex_prop_t dispex_prop_t;
typedef struct _property_desc_t property_desc_t; typedef struct _property_desc_t property_desc_t;
@ -398,11 +399,6 @@ struct _property_desc_t {
jsdisp_t *setter; jsdisp_t *setter;
}; };
typedef struct {
EXCEPINFO ei;
jsval_t val;
} jsexcept_t;
typedef struct { typedef struct {
unsigned index; unsigned index;
unsigned length; unsigned length;
@ -424,7 +420,7 @@ struct _script_ctx_t {
LCID lcid; LCID lcid;
cc_ctx_t *cc; cc_ctx_t *cc;
JSCaller *jscaller; JSCaller *jscaller;
jsexcept_t ei; jsexcept_t *ei;
heap_pool_t tmp_heap; heap_pool_t tmp_heap;
@ -462,7 +458,6 @@ struct _script_ctx_t {
}; };
void script_release(script_ctx_t*) DECLSPEC_HIDDEN; void script_release(script_ctx_t*) DECLSPEC_HIDDEN;
void clear_ei(script_ctx_t*) DECLSPEC_HIDDEN;
static inline void script_addref(script_ctx_t *ctx) static inline void script_addref(script_ctx_t *ctx)
{ {

View File

@ -286,10 +286,8 @@ static INT index_from_val(script_ctx_t *ctx, jsval_t v)
HRESULT hres; HRESULT hres;
hres = to_number(ctx, v, &n); hres = to_number(ctx, v, &n);
if(FAILED(hres)) { if(FAILED(hres))
clear_ei(ctx); /* FIXME: Move ignoring exceptions to to_primitive */
return 0; return 0;
}
n = floor(n); n = floor(n);
return is_int32(n) ? n : 0; return is_int32(n) ? n : 0;

View File

@ -873,14 +873,16 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt) HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt)
{ {
jsexcept_t ei;
jsval_t val; jsval_t val;
HRESULT hres; HRESULT hres;
clear_ei(ctx);
hres = variant_to_jsval(src, &val); hres = variant_to_jsval(src, &val);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
enter_script(ctx, &ei);
switch(vt) { switch(vt) {
case VT_I2: case VT_I2:
case VT_I4: { case VT_I4: {
@ -948,6 +950,7 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY
} }
jsval_release(val); jsval_release(val);
leave_script(ctx, hres);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;