Skip to content

Commit 1485ed4

Browse files
committed
[[ Bug 19416 ]] Refactor object message clear
In order to fully purge the pending messages of messages for a given object when the object is removed from the object tree, we must recursively remove these messages for all children of the deleted object.
1 parent 5fb1887 commit 1485ed4

File tree

10 files changed

+88
-16
lines changed

10 files changed

+88
-16
lines changed

docs/notes/bugfix-19416.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Ensure all object messages are cleared when obj or ancestor is deleted

engine/src/card.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ Boolean MCCard::del(bool p_check_flag)
11581158
}
11591159
else
11601160
{
1161-
optr->getref()->uncacheid();
1161+
optr->getref()->removereferences();
11621162
getstack()->removecontrol(optr->getref());
11631163
}
11641164
MCCdata *dptr = optr->getref()->getdata(obj_id, False);
@@ -1169,7 +1169,7 @@ Boolean MCCard::del(bool p_check_flag)
11691169
while (optr != objptrs);
11701170
}
11711171

1172-
uncacheid();
1172+
removereferences();
11731173

11741174
// MCObject now does things on del(), so we must make sure we finish by
11751175
// calling its implementation.

engine/src/control.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,20 +500,20 @@ Boolean MCControl::del(bool p_check_flag)
500500
switch (parent->gettype())
501501
{
502502
case CT_STACK:
503-
uncacheid();
503+
removereferences();
504504
parent.GetAs<MCStack>()->removecontrol(this);
505505
break;
506506

507507
case CT_CARD:
508508
if (!parent.GetAs<MCCard>()->removecontrol(this, False, True))
509509
return False;
510-
uncacheid();
510+
removereferences();
511511
getstack()->removecontrol(this);
512512
break;
513513

514514
case CT_GROUP:
515515
parent.GetAs<MCGroup>()->removecontrol(this, True);
516-
uncacheid();
516+
removereferences();
517517
break;
518518

519519
default:

engine/src/group.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,20 +1031,20 @@ void MCGroup::applyrect(const MCRectangle &nrect)
10311031
}
10321032
}
10331033

1034-
void MCGroup::uncacheid()
1034+
void MCGroup::removereferences()
10351035
{
10361036
if (controls != NULL)
10371037
{
10381038
MCControl *t_control;
10391039
t_control = controls;
10401040
do
1041-
{ t_control -> uncacheid();
1041+
{ t_control -> removereferences();
10421042
t_control = t_control -> next();
10431043
}
10441044
while(t_control != controls);
10451045
}
10461046

1047-
MCObject::uncacheid();
1047+
MCObject::removereferences();
10481048
}
10491049

10501050
bool MCGroup::isdeletable(bool p_check_flag)

engine/src/group.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class MCGroup : public MCControl, public MCMixinObjectHandle<MCGroup>
9292
virtual Boolean doubleup(uint2 which);
9393
virtual void applyrect(const MCRectangle &nrect);
9494

95-
virtual void uncacheid(void);
95+
virtual void removereferences(void);
9696
virtual Boolean del(bool p_check_flag);
9797
virtual void recompute();
9898

engine/src/object.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -853,10 +853,14 @@ void MCObject::deselect()
853853
state &= ~CS_SELECTED;
854854
}
855855

856-
void MCObject::uncacheid()
856+
void MCObject::removereferences()
857857
{
858858
if (m_in_id_cache)
859859
getstack()->uncacheobjectbyid(this);
860+
861+
MCscreen->cancelmessageobject(this, NULL);
862+
removefrom(MCfrontscripts);
863+
removefrom(MCbackscripts);
860864
}
861865

862866
bool MCObject::isdeletable(bool p_check_flag)
@@ -873,10 +877,6 @@ bool MCObject::isdeletable(bool p_check_flag)
873877

874878
Boolean MCObject::del(bool p_check_flag)
875879
{
876-
MCscreen->cancelmessageobject(this, NULL);
877-
removefrom(MCfrontscripts);
878-
removefrom(MCbackscripts);
879-
880880
// If the object is marked as being used as a parentScript, flush the parentScript
881881
// table so we don't get any dangling pointers.
882882
if (m_is_parent_script)

engine/src/object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ class MCObject :
672672
virtual void undo(Ustruct *us);
673673
virtual void freeundo(Ustruct *us);
674674

675-
virtual void uncacheid(void);
675+
virtual void removereferences(void);
676676

677677
// [[ C++11 ]] MSVC doesn't support typename here while other compilers require it
678678
#ifdef _MSC_VER

engine/src/stack.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,8 @@ Boolean MCStack::del(bool p_check_flag)
14401440
needs = NULL;
14411441
}
14421442

1443+
removereferences();
1444+
14431445
uint2 i = 0;
14441446
while (i < MCnusing)
14451447
if (MCusing[i] == this)
@@ -1457,6 +1459,51 @@ Boolean MCStack::del(bool p_check_flag)
14571459
return MCObject::del(true);
14581460
}
14591461

1462+
void MCStack::removereferences()
1463+
{
1464+
if (controls != NULL)
1465+
{
1466+
MCControl *t_control = controls;
1467+
do
1468+
{ t_control -> removereferences();
1469+
t_control = t_control -> next();
1470+
}
1471+
while(t_control != controls);
1472+
}
1473+
1474+
if (aclips != NULL)
1475+
{
1476+
MCAudioClip *t_aclip = aclips;
1477+
do
1478+
{ t_aclip -> removereferences();
1479+
t_aclip = t_aclip -> next();
1480+
}
1481+
while(t_aclip != aclips);
1482+
}
1483+
1484+
if (vclips != NULL)
1485+
{
1486+
MCVideoClip *t_vclip = vclips;
1487+
do
1488+
{ t_vclip -> removereferences();
1489+
t_vclip = t_vclip -> next();
1490+
}
1491+
while(t_vclip != vclips);
1492+
}
1493+
1494+
if (cards != NULL)
1495+
{
1496+
MCCard *t_card = cards;
1497+
do
1498+
{ t_card -> removereferences();
1499+
t_card = t_card -> next();
1500+
}
1501+
while(t_card != cards);
1502+
}
1503+
1504+
MCObject::removereferences();
1505+
}
1506+
14601507
void MCStack::paste(void)
14611508
{
14621509
if (MCdispatcher -> findstackname(getname()) != NULL)

engine/src/stack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ class MCStack : public MCObject, public MCMixinObjectHandle<MCStack>
353353
virtual void timer(MCNameRef mptr, MCParameter *params);
354354
virtual void applyrect(const MCRectangle &nrect);
355355

356+
virtual void removereferences(void);
356357
virtual Boolean del(bool p_check_flag);
357358
virtual bool isdeletable(bool p_check_flag);
358359

tests/lcs/core/engine/send.livecodescript

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,27 @@ on TestSendParams
3131

3232
send tSendScript to tStack
3333
TestAssert "send script with multiple params", the result is "2"
34-
end TestSendParams
34+
end TestSendParams
35+
36+
private function MessageExists pId
37+
repeat for each line tLine in the pendingMessages
38+
if item 1 of tLine is pId then
39+
return true
40+
end if
41+
end repeat
42+
return false
43+
end MessageExists
44+
45+
46+
on TestSendToSubobj
47+
local tStack, tMsgId
48+
create stack
49+
put the short name of it into tStack
50+
set the defaultStack to tStack
51+
create button
52+
send "mouseUp" to it in 5 millisecs
53+
put the result into tMsgId
54+
delete stack tStack
55+
56+
TestAssert "message canceled on delete", not MessageExists(tMsgId)
57+
end TestSendToSubobj

0 commit comments

Comments
 (0)