diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 88c63811386..57882bf499e 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -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--;
diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c
index bf2045c7c41..7e49e31a5d5 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)