From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 22 ++++++------ dlls/jscript/global.c | 2 +- dlls/jscript/jscript.c | 2 +- dlls/jscript/jscript.h | 2 +- dlls/jscript/set.c | 5 --- dlls/jscript/tests/run.c | 75 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 87 insertions(+), 21 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ae5ff655914..404d9aa6b7a 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -775,7 +775,7 @@ static jsdisp_t *gc_stack_pop(struct gc_ctx *gc_ctx) return obj; }
-HRESULT gc_run(script_ctx_t *ctx) +HRESULT gc_run(void) { /* Save original refcounts in a linked list of chunks */ struct chunk @@ -823,13 +823,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: @@ -837,7 +837,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); @@ -873,12 +873,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; @@ -888,7 +888,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; @@ -977,8 +977,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) @@ -997,7 +995,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--; @@ -2183,7 +2181,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
/* FIXME: Use better heuristics to decide when to run the GC */ if(GetTickCount() - thread_data->gc_last_tick > 30000) - gc_run(ctx); + gc_run();
TRACE("%p (%p)\n", dispex, prototype);
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 997b2542a9e..fe9af7a48b3 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -554,7 +554,7 @@ static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, jsval_t vthi static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return gc_run(ctx); + return gc_run(); }
static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 42ac8a5fcf7..b9dbeda90cb 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -506,7 +506,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) }
script_globals_release(This->ctx); - gc_run(This->ctx); + gc_run();
/* FALLTHROUGH */ case SCRIPTSTATE_UNINITIALIZED: diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 3c4f4483275..218d87a342e 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -159,7 +159,7 @@ enum gc_traverse_op { HRESULT create_named_item_script_obj(script_ctx_t*,named_item_t*); named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned); void release_named_item(named_item_t*); -HRESULT gc_run(script_ctx_t*); +HRESULT gc_run(void); HRESULT gc_process_linked_obj(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*,jsdisp_t*,void**); HRESULT gc_process_linked_val(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*,jsval_t*);
diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 4caa338ae67..5b5a9b9c811 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -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); diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 509f01e3211..db1e95dc844 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -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)