mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 10:47:18 +00:00
jscript: Use a jsdisp to hold refs for scopes.
So the garbage collector can traverse it. Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
parent
07761336d6
commit
b0db79d769
|
@ -422,15 +422,40 @@ static inline void clear_acc(script_ctx_t *ctx)
|
|||
ctx->acc = jsval_undefined();
|
||||
}
|
||||
|
||||
static HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret)
|
||||
static void scope_destructor(jsdisp_t *dispex)
|
||||
{
|
||||
scope_chain_t *scope = CONTAINING_RECORD(dispex, scope_chain_t, dispex);
|
||||
|
||||
if(scope->next)
|
||||
scope_release(scope->next);
|
||||
|
||||
if(scope->obj)
|
||||
IDispatch_Release(scope->obj);
|
||||
free(scope);
|
||||
}
|
||||
|
||||
static const builtin_info_t scope_info = {
|
||||
JSCLASS_NONE,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
scope_destructor,
|
||||
};
|
||||
|
||||
static HRESULT scope_push(script_ctx_t *ctx, scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret)
|
||||
{
|
||||
scope_chain_t *new_scope;
|
||||
HRESULT hres;
|
||||
|
||||
new_scope = malloc(sizeof(scope_chain_t));
|
||||
new_scope = calloc(1, sizeof(scope_chain_t));
|
||||
if(!new_scope)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
new_scope->ref = 1;
|
||||
hres = init_dispex(&new_scope->dispex, ctx, &scope_info, NULL);
|
||||
if(FAILED(hres)) {
|
||||
free(new_scope);
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (obj)
|
||||
IDispatch_AddRef(obj);
|
||||
|
@ -453,19 +478,6 @@ static void scope_pop(scope_chain_t **scope)
|
|||
scope_release(tmp);
|
||||
}
|
||||
|
||||
void scope_release(scope_chain_t *scope)
|
||||
{
|
||||
if(--scope->ref)
|
||||
return;
|
||||
|
||||
if(scope->next)
|
||||
scope_release(scope->next);
|
||||
|
||||
if (scope->obj)
|
||||
IDispatch_Release(scope->obj);
|
||||
free(scope);
|
||||
}
|
||||
|
||||
static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
|
||||
{
|
||||
IDispatchEx *dispex;
|
||||
|
@ -975,7 +987,7 @@ static HRESULT interp_push_with_scope(script_ctx_t *ctx)
|
|||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = scope_push(ctx->call_ctx->scope, to_jsdisp(disp), disp, &ctx->call_ctx->scope);
|
||||
hres = scope_push(ctx, ctx->call_ctx->scope, to_jsdisp(disp), disp, &ctx->call_ctx->scope);
|
||||
IDispatch_Release(disp);
|
||||
return hres;
|
||||
}
|
||||
|
@ -989,7 +1001,7 @@ static HRESULT interp_push_block_scope(script_ctx_t *ctx)
|
|||
|
||||
TRACE("scope_index %u.\n", scope_index);
|
||||
|
||||
hres = scope_push(ctx->call_ctx->scope, NULL, NULL, &frame->scope);
|
||||
hres = scope_push(ctx, ctx->call_ctx->scope, NULL, NULL, &frame->scope);
|
||||
|
||||
if (FAILED(hres) || !scope_index)
|
||||
return hres;
|
||||
|
@ -1004,7 +1016,7 @@ static HRESULT interp_pop_scope(script_ctx_t *ctx)
|
|||
{
|
||||
TRACE("\n");
|
||||
|
||||
if(ctx->call_ctx->scope->ref > 1) {
|
||||
if(ctx->call_ctx->scope->dispex.ref > 1) {
|
||||
HRESULT hres = detach_variable_object(ctx, ctx->call_ctx, FALSE);
|
||||
if(FAILED(hres))
|
||||
ERR("Failed to detach variable object: %08lx\n", hres);
|
||||
|
@ -1201,7 +1213,7 @@ static HRESULT interp_enter_catch(script_ctx_t *ctx)
|
|||
hres = jsdisp_propput_name(scope_obj, ident, v);
|
||||
jsval_release(v);
|
||||
if(SUCCEEDED(hres))
|
||||
hres = scope_push(ctx->call_ctx->scope, scope_obj, to_disp(scope_obj), &ctx->call_ctx->scope);
|
||||
hres = scope_push(ctx, ctx->call_ctx->scope, scope_obj, to_disp(scope_obj), &ctx->call_ctx->scope);
|
||||
jsdisp_release(scope_obj);
|
||||
return hres;
|
||||
}
|
||||
|
@ -2919,7 +2931,7 @@ static void pop_call_frame(script_ctx_t *ctx)
|
|||
assert(frame->scope == frame->base_scope);
|
||||
|
||||
/* If current scope will be kept alive, we need to transfer local variables to its variable object. */
|
||||
if(frame->scope && frame->scope->ref > 1) {
|
||||
if(frame->scope && frame->scope->dispex.ref > 1) {
|
||||
HRESULT hres = detach_variable_object(ctx, frame, TRUE);
|
||||
if(FAILED(hres))
|
||||
ERR("Failed to detach variable object: %08lx\n", hres);
|
||||
|
@ -3191,7 +3203,7 @@ static HRESULT setup_scope(script_ctx_t *ctx, call_frame_t *frame, scope_chain_t
|
|||
|
||||
frame->pop_variables = i;
|
||||
|
||||
hres = scope_push(scope_chain, variable_object, to_disp(variable_object), &scope);
|
||||
hres = scope_push(ctx, scope_chain, variable_object, to_disp(variable_object), &scope);
|
||||
if(FAILED(hres)) {
|
||||
stack_popn(ctx, ctx->stack_top - orig_stack);
|
||||
return hres;
|
||||
|
|
|
@ -222,7 +222,7 @@ static inline bytecode_t *bytecode_addref(bytecode_t *code)
|
|||
}
|
||||
|
||||
typedef struct _scope_chain_t {
|
||||
LONG ref;
|
||||
jsdisp_t dispex; /* FIXME: don't wrap it in a jsdisp (it holds ref and traverse for the garbage collector) */
|
||||
jsdisp_t *jsobj;
|
||||
IDispatch *obj;
|
||||
unsigned int scope_index;
|
||||
|
@ -230,14 +230,17 @@ typedef struct _scope_chain_t {
|
|||
struct _scope_chain_t *next;
|
||||
} scope_chain_t;
|
||||
|
||||
void scope_release(scope_chain_t*) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline scope_chain_t *scope_addref(scope_chain_t *scope)
|
||||
{
|
||||
scope->ref++;
|
||||
jsdisp_addref(&scope->dispex);
|
||||
return scope;
|
||||
}
|
||||
|
||||
static inline void scope_release(scope_chain_t *scope)
|
||||
{
|
||||
jsdisp_release(&scope->dispex);
|
||||
}
|
||||
|
||||
struct _jsexcept_t {
|
||||
HRESULT error;
|
||||
|
||||
|
|
Loading…
Reference in a new issue