1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-08 20:06:18 +00:00

jscript: Allow garbage collection between different jscript contexts.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2023-12-12 19:57:37 +02:00 committed by Alexandre Julliard
parent bc45b43a49
commit 64009b9c9f
3 changed files with 82 additions and 16 deletions

View File

@ -820,13 +820,13 @@ HRESULT gc_run(script_ctx_t *ctx)
for(prop = obj->props, props_end = prop + obj->prop_cnt; prop < props_end; prop++) {
switch(prop->type) {
case PROP_JSVAL:
if(is_object_instance(prop->u.val) && (link = to_jsdisp(get_object(prop->u.val))) && link->ctx == ctx)
if(is_object_instance(prop->u.val) && (link = to_jsdisp(get_object(prop->u.val))))
link->ref--;
break;
case PROP_ACCESSOR:
if(prop->u.accessor.getter && prop->u.accessor.getter->ctx == ctx)
if(prop->u.accessor.getter)
prop->u.accessor.getter->ref--;
if(prop->u.accessor.setter && prop->u.accessor.setter->ctx == ctx)
if(prop->u.accessor.setter)
prop->u.accessor.setter->ref--;
break;
default:
@ -834,7 +834,7 @@ HRESULT gc_run(script_ctx_t *ctx)
}
}
if(obj->prototype && obj->prototype->ctx == ctx)
if(obj->prototype)
obj->prototype->ref--;
if(obj->builtin_info->gc_traverse)
obj->builtin_info->gc_traverse(&gc_ctx, GC_TRAVERSE_SPECULATIVELY, obj);
@ -870,12 +870,12 @@ HRESULT gc_run(script_ctx_t *ctx)
default:
continue;
}
if(link && link->gc_marked && link->ctx == ctx) {
if(link && link->gc_marked) {
hres = gc_stack_push(&gc_ctx, link);
if(FAILED(hres))
break;
}
if(link2 && link2->gc_marked && link2->ctx == ctx) {
if(link2 && link2->gc_marked) {
hres = gc_stack_push(&gc_ctx, link2);
if(FAILED(hres))
break;
@ -885,7 +885,7 @@ HRESULT gc_run(script_ctx_t *ctx)
if(FAILED(hres))
break;
if(obj2->prototype && obj2->prototype->gc_marked && obj2->prototype->ctx == ctx) {
if(obj2->prototype && obj2->prototype->gc_marked) {
hres = gc_stack_push(&gc_ctx, obj2->prototype);
if(FAILED(hres))
break;
@ -974,8 +974,6 @@ HRESULT gc_process_linked_obj(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsd
return S_OK;
}
if(link->ctx != obj->ctx)
return S_OK;
if(op == GC_TRAVERSE_SPECULATIVELY)
link->ref--;
else if(link->gc_marked)
@ -994,7 +992,7 @@ HRESULT gc_process_linked_val(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsd
return S_OK;
}
if(!is_object_instance(*link) || !(jsdisp = to_jsdisp(get_object(*link))) || jsdisp->ctx != obj->ctx)
if(!is_object_instance(*link) || !(jsdisp = to_jsdisp(get_object(*link))))
return S_OK;
if(op == GC_TRAVERSE_SPECULATIVELY)
jsdisp->ref--;

View File

@ -745,11 +745,6 @@ static HRESULT WeakMap_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
if(!key)
return JS_E_KEY_NOT_OBJECT;
if(key->ctx != ctx) {
FIXME("different ctx not supported\n");
return JS_E_KEY_NOT_OBJECT;
}
if((entry = get_weakmap_entry(weakmap, key))) {
jsval_t val;
hres = jsval_copy(value, &val);

View File

@ -3596,9 +3596,14 @@ static void test_destructors(void)
"a.ref = { 'ref': Math, 'a': a }; b.ref = Math.ref;\n"
"a.self = a; b.self = b; c.self = c;\n"
"})(), true";
static DISPID propput_dispid = DISPID_PROPERTYPUT;
IActiveScript *script, *script2;
IDispatchEx *dispex, *dispex2;
IActiveScriptParse *parser;
IActiveScript *script;
DISPPARAMS dp = { 0 };
VARIANT v;
DISPID id;
BSTR str;
HRESULT hres;
V_VT(&v) = VT_EMPTY;
@ -3643,6 +3648,74 @@ static void test_destructors(void)
CHECK_CALLED(testdestrobj);
IActiveScript_Release(script);
/* Create a cyclic ref across two jscript engines */
V_VT(&v) = VT_EMPTY;
hres = parse_script_expr(cyclic_refs, &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v));
hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser);
ok(hres == S_OK, "Could not get IActiveScriptParse: %08lx\n", hres);
V_VT(&v) = VT_EMPTY;
hres = IActiveScriptParse_ParseScriptText(parser, L"Math.ref", NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &v, NULL);
ok(hres == S_OK, "ParseScriptText failed: %08lx\n", hres);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(v) = NULL\n");
hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
VariantClear(&v);
V_VT(&v) = VT_EMPTY;
hres = parse_script_expr(L"new Object()", &v, &script2);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(v) = NULL\n");
hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex2);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
VariantClear(&v);
dp.cArgs = dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &propput_dispid;
dp.rgvarg = &v;
str = SysAllocString(L"diff_ctx");
hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure, &id);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
SysFreeString(str);
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (IDispatch*)dispex2;
hres = IDispatchEx_Invoke(dispex, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dp, NULL, NULL, NULL);
ok(hres == S_OK, "Invoke failed: %08lx\n", hres);
str = SysAllocString(L"ref");
hres = IDispatchEx_GetDispID(dispex2, str, fdexNameEnsure, &id);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
SysFreeString(str);
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (IDispatch*)dispex;
hres = IDispatchEx_Invoke(dispex2, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dp, NULL, NULL, NULL);
ok(hres == S_OK, "Invoke failed: %08lx\n", hres);
IDispatchEx_Release(dispex2);
IDispatchEx_Release(dispex);
SET_EXPECT(testdestrobj);
V_VT(&v) = VT_EMPTY;
hres = IActiveScriptParse_ParseScriptText(parser, L"Math.ref = undefined, CollectGarbage(), true",
NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &v, NULL);
ok(hres == S_OK, "ParseScriptText failed: %08lx\n", hres);
ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v));
IActiveScriptParse_Release(parser);
CHECK_CALLED(testdestrobj);
IActiveScript_Release(script2);
IActiveScript_Release(script);
}
static void test_eval(void)