jscript: Allow garbage collection between different jscript contexts.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
parent
bc45b43a49
commit
64009b9c9f
3 changed files with 82 additions and 16 deletions
|
@ -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--;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue