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);
dispex_prop_t *prop;
jsexcept_t ei;
HRESULT hres;
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;
}
clear_ei(This->ctx);
enter_script(This->ctx, &ei);
switch(wFlags) {
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);
if(FAILED(hres))
return hres;
break;
hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller);
if(argv != buf)
@ -1570,12 +1571,13 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
if(i == pdp->cNamedArgs) {
TRACE("no value to set\n");
return DISP_E_PARAMNOTOPTIONAL;
hres = DISP_E_PARAMNOTOPTIONAL;
break;
}
hres = variant_to_jsval(pdp->rgvarg+i, &val);
if(FAILED(hres))
return hres;
break;
hres = prop_put(This, prop, val);
jsval_release(val);
@ -1583,12 +1585,11 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
}
default:
FIXME("Unimplemented flags %x\n", wFlags);
return E_INVALIDARG;
hres = E_INVALIDARG;
break;
}
if(pei)
*pei = This->ctx->ei.ei;
return hres;
return leave_script(This->ctx, hres);
}
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);
}
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)
{
if(--scope->ref)
@ -867,8 +860,8 @@ static HRESULT interp_throw(script_ctx_t *ctx)
{
TRACE("\n");
jsval_release(ctx->ei.val);
ctx->ei.val = stack_pop(ctx);
jsval_release(ctx->ei->value);
ctx->ei->value = stack_pop(ctx);
return DISP_E_EXCEPTION;
}
@ -964,7 +957,7 @@ static HRESULT interp_end_finally(script_ctx_t *ctx)
if(!get_bool(v)) {
TRACE("passing exception\n");
ctx->ei.val = stack_pop(ctx);
ctx->ei->value = stack_pop(ctx);
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};
WARN("Exception %08x %s", exception_hres, debugstr_jsval(ctx->ei.val));
if(jsval_type(ctx->ei.val) == JSV_OBJECT) {
error_obj = to_jsdisp(get_object(ctx->ei.val));
WARN("Exception %08x %s", exception_hres, debugstr_jsval(ctx->ei->value));
if(jsval_type(ctx->ei->value) == JSV_OBJECT) {
error_obj = to_jsdisp(get_object(ctx->ei->value));
if(error_obj) {
hres = jsdisp_propget_name(error_obj, messageW, &msg);
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;
if(catch_off) assert(frame->bytecode->instrs[frame->ip].op == OP_enter_catch);
except_val = ctx->ei.val;
ctx->ei.val = jsval_undefined();
clear_ei(ctx);
except_val = ctx->ei->value;
ctx->ei->value = jsval_undefined();
/* keep current except_frame if we're entering catch block with finally block associated */
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;
}
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;
struct _parser_ctx_t;

View File

@ -20,6 +20,7 @@
#include <math.h>
#include "jscript.h"
#include "engine.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))
return hres;
jsval_release(ctx->ei.val);
ctx->ei.val = jsval_obj(err);
jsval_release(ctx->ei->value);
ctx->ei->value = jsval_obj(err);
return error;
}

View File

@ -70,7 +70,6 @@ void script_release(script_ctx_t *ctx)
return;
jsval_release(ctx->acc);
clear_ei(ctx);
if(ctx->cc)
release_cc(ctx->cc);
heap_pool_free(&ctx->tmp_heap);
@ -102,13 +101,39 @@ static inline BOOL is_started(script_ctx_t *ctx)
|| 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)
{
HRESULT hres;
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);
IActiveScriptSite_OnLeaveScript(This->site);
@ -141,9 +166,14 @@ static void clear_persistent_code_list(JScript *This)
static void exec_queued_code(JScript *This)
{
bytecode_t *iter;
jsexcept_t ei;
HRESULT hres;
LIST_FOR_EACH_ENTRY(iter, &This->queued_code, bytecode_t, entry)
exec_global_code(This, iter);
LIST_FOR_EACH_ENTRY(iter, &This->queued_code, bytecode_t, entry) {
enter_script(This->ctx, &ei);
hres = exec_global_code(This, iter);
leave_script(This->ctx, hres);
}
clear_script_queue(This);
}
@ -723,7 +753,6 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
ctx->safeopt = This->safeopt;
ctx->version = This->version;
ctx->html_mode = This->html_mode;
ctx->ei.val = jsval_undefined();
ctx->acc = jsval_undefined();
heap_pool_init(&ctx->tmp_heap);
@ -765,6 +794,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
{
JScript *This = impl_from_IActiveScriptParse(iface);
bytecode_t *code;
jsexcept_t ei;
HRESULT hres;
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)
return E_UNEXPECTED;
enter_script(This->ctx, &ei);
hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLine, NULL, pstrDelimiter,
(dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, This->is_encode, &code);
if(FAILED(hres))
return hres;
return leave_script(This->ctx, hres);
if(dwFlags & SCRIPTTEXT_ISEXPRESSION) {
jsval_t r;
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);
if(SUCCEEDED(hres)) {
if(pvarResult)
@ -793,7 +823,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
}
IActiveScriptSite_OnLeaveScript(This->site);
return hres;
return leave_script(This->ctx, hres);
}
code->is_persistent = (dwFlags & SCRIPTTEXT_ISPERSISTENT) != 0;
@ -804,17 +834,16 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
*/
if(!pvarResult && !is_started(This->ctx)) {
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(code->is_persistent)
list_add_tail(&This->persistent_code, &code->entry);
else
release_bytecode(code);
if(FAILED(hres))
if(FAILED(hres = leave_script(This->ctx, hres)))
return hres;
if(pvarResult)
@ -862,6 +891,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
bytecode_t *code;
jsdisp_t *dispex;
jsexcept_t ei;
HRESULT hres;
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)
return E_UNEXPECTED;
enter_script(This->ctx, &ei);
hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLineNumber, pstrFormalParams,
pstrDelimiter, FALSE, This->is_encode, &code);
if(FAILED(hres)) {
WARN("Parse failed %08x\n", hres);
return hres;
}
hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex);
if(SUCCEEDED(hres))
hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex);
release_bytecode(code);
hres = leave_script(This->ctx, hres);
if(FAILED(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)
{
JScript *This = impl_from_IVariantChangeType(iface);
jsexcept_t ei;
VARIANT res;
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) {
FIXME("Object uninitialized\n");
return E_UNEXPECTED;
}
enter_script(This->ctx, &ei);
hres = variant_change_type(This->ctx, &res, src, vt);
hres = leave_script(This->ctx, hres);
if(FAILED(hres))
return hres;

View File

@ -48,6 +48,7 @@
typedef struct _jsval_t jsval_t;
typedef struct _jsstr_t jsstr_t;
typedef struct _jsexcept_t jsexcept_t;
typedef struct _script_ctx_t script_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t;
typedef struct _property_desc_t property_desc_t;
@ -398,11 +399,6 @@ struct _property_desc_t {
jsdisp_t *setter;
};
typedef struct {
EXCEPINFO ei;
jsval_t val;
} jsexcept_t;
typedef struct {
unsigned index;
unsigned length;
@ -424,7 +420,7 @@ struct _script_ctx_t {
LCID lcid;
cc_ctx_t *cc;
JSCaller *jscaller;
jsexcept_t ei;
jsexcept_t *ei;
heap_pool_t tmp_heap;
@ -462,7 +458,6 @@ struct _script_ctx_t {
};
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)
{

View File

@ -286,10 +286,8 @@ static INT index_from_val(script_ctx_t *ctx, jsval_t v)
HRESULT hres;
hres = to_number(ctx, v, &n);
if(FAILED(hres)) {
clear_ei(ctx); /* FIXME: Move ignoring exceptions to to_primitive */
if(FAILED(hres))
return 0;
}
n = floor(n);
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)
{
jsexcept_t ei;
jsval_t val;
HRESULT hres;
clear_ei(ctx);
hres = variant_to_jsval(src, &val);
if(FAILED(hres))
return hres;
enter_script(ctx, &ei);
switch(vt) {
case VT_I2:
case VT_I4: {
@ -948,6 +950,7 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY
}
jsval_release(val);
leave_script(ctx, hres);
if(FAILED(hres))
return hres;