<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"Calibri Light";
        panose-1:2 15 3 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
p.MsoNoSpacing, li.MsoNoSpacing, div.MsoNoSpacing
        {mso-style-priority:1;
        margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal">Hi Christoph,</p>
<p class="MsoNormal">I'm enclosing fixed tests 19 and 20 with the test block you suggested and an updated Debugger fix for your review (This is how I think the debugger's Abandon/Terminate should work but you may come up with a better implementation).</p>
<p class="MsoNormal">Hope this helps :)</p>
<p class="MsoNormal">Best,</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNoSpacing"><span lang="CS">--</span></p>
<p class="MsoNoSpacing"><strong><span style="font-family:"Calibri Light",sans-serif;color:#333333;font-weight:normal">Jaromír Matas</span></strong><span style="font-family:"Calibri Light",sans-serif;color:#555555"><o:p></o:p></span></p>
<p class="MsoNoSpacing"><span style="font-family:"Calibri Light",sans-serif;color:#2E75B6">mail@jaromir.net</span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="border:none;padding:0in"><b>From: </b><a href="mailto:mail@jaromir.net">Jaromir Matas</a><br>
<b>Sent: </b>Saturday, May 21, 2022 11:19<br>
<b>To: </b><a href="mailto:squeak-dev@lists.squeakfoundation.org">The general-purpose Squeak developers list</a>;
<a href="mailto:christoph.thiede@student.hpi.uni-potsdam.de">christoph.thiede@student.hpi.uni-potsdam.de</a><br>
<b>Subject: </b>Re: [squeak-dev] The Trunk: ToolsTests-ct.107.mcz</p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Hi Christoph,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I enclose a fix for the Debugger issue mentioned below, i.e. the inconsistent behavior when terminating the Debugger – whether via Abandon or via `terminate process`; the only difference between the two should be the choice of the termination
 method. Currently each of them uses a different execution path leading to an erroneous behavior when terminating the Debugger via `terminate process`.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks for taking a look at this. Would you like me to send it to the Inbox?<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Best,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNoSpacing"><span lang="CS">--</span></p>
<p class="MsoNoSpacing"><strong><span style="font-family:"Calibri Light",sans-serif;color:#333333;font-weight:normal">Jaromír Matas</span></strong><span style="font-family:"Calibri Light",sans-serif;color:#555555"><o:p></o:p></span></p>
<p class="MsoNoSpacing"><span style="font-family:"Calibri Light",sans-serif;color:#2E75B6">mail@jaromir.net</span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b>From: </b><a href="mailto:mail@jaromir.net">Jaromir Matas</a><br>
<b>Sent: </b>Friday, May 20, 2022 16:49<br>
<b>To: </b><a href="mailto:squeak-dev@lists.squeakfoundation.org">The general-purpose Squeak developers list</a>;
<a href="mailto:christoph.thiede@student.hpi.uni-potsdam.de">christoph.thiede@student.hpi.uni-potsdam.de</a><br>
<b>Subject: </b>Re: [squeak-dev] The Trunk: ToolsTests-ct.107.mcz<o:p></o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Hi Christoph,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">sorry to be a pest: this issue has likely escaped your attention and has recently reemerged in Lauren's test runner report :)
<o:p></o:p></p>
<p class="MsoNormal">thanks :)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">best, <o:p></o:p></p>
<p class="MsoNormal">Jaromir<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNoSpacing"><span lang="CS">--</span></p>
<p class="MsoNoSpacing"><strong><span style="font-family:"Calibri Light",sans-serif;color:#333333;font-weight:normal">Jaromír Matas</span></strong><span style="font-family:"Calibri Light",sans-serif;color:#555555"><o:p></o:p></span></p>
<p class="MsoNoSpacing"><span style="font-family:"Calibri Light",sans-serif;color:#2E75B6">mail@jaromir.net</span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><img border="0" width="694" height="2" style="width:7.2291in;height:.0208in" id="Horizontal_x0020_Line_x0020_1" src="cid:image002.png@01D86D04.8EB39460"><o:p></o:p></p>
<div id="divRplyFwdMsg">
<p class="MsoNormal"><b><span style="color:black">From:</span></b><span style="color:black"> Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> on behalf of mail@jaromir.net <mail@jaromir.net><br>
<b>Sent:</b> Monday, January 10, 2022 8:21:14 PM<br>
<b>To:</b> squeak-dev@lists.squeakfoundation.org <squeak-dev@lists.squeakfoundation.org>; christoph.thiede@student.hpi.uni-potsdam.de <christoph.thiede@student.hpi.uni-potsdam.de><br>
<b>Subject:</b> Re: [squeak-dev] The Trunk: ToolsTests-ct.107.mcz</span> <o:p></o:p></p>
<div>
<p class="MsoNormal"> <o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt">Hi Christoph,<br>
<br>
yes, the expectations for this block are just right :)<br>
<br>
I tried to put the block in the testcase but the error windows that pop up behave a bit erratically - I guess it's because of the debugger #windowIsClosing issue described in: (and as a consequence some of the other assertions fail)<br>
<br>
<a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217724.html">http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217724.html</a><br>
<br>
I think all three modes of closing the debugger (destroy, aggressively, normally) should be treated equally to avoid such unexpected side effects. Please review the above and let me know what you think.<br>
<br>
Thanks!<br>
<br>
best,<br>
~~~<br>
^[^    Jaromir<br>
<br>
Sent from Squeak Inbox Talk<br>
<br>
On 2022-01-10T19:53:09+01:00, christoph.thiede@student.hpi.uni-potsdam.de wrote:<br>
<br>
> Hi Jaromir,<br>
> <br>
> you're totally right, sorry for the confusion. How would you think about this test block instead?<br>
> <br>
>        [[x := 1] ensure:<br>
>                [[y := 1.<br>
>                self error: #first.<br>
>                y := 2] ensure:<br>
>                        [z := 1.<br>
>                        self error: #second.<br>
>                        z := 2]].<br>
>        x := 2] value.<br>
> <br>
> If you abandon #first and proceed #second, {x. y. z} will be correctly #(1 1 2).<br>
> If you terminate #first and proceed #second, {x. y. z} should be #(1 2 2).<br>
> <br>
> Would you agree with that? :)<br>
> If yes, I will upload this to the Trunk, try to make the tests more self-explaining, and comment out the #isTerminated assertions for now.<br>
> <br>
> Best,<br>
> Christoph<br>
> <br>
> ---<br>
> Sent from Squeak Inbox Talk<br>
> <br>
> On 2022-01-03T16:23:01+01:00, mail at jaromir.net wrote:<br>
> <br>
> > Hi Christoph,<br>
> > <br>
> > I'm pretty sure this test (test20TerminateProcess) isn't working correctly; the expectations are set as if testing debugger's Proceed, not Terminate. Debugger terminate in this scenario will be answering identically as Abandon because you proceed through
 the second error inside the ensure argument block :)<br>
> > <br>
> > Thanks,<br>
> > <br>
> > best,<br>
> > ~~~<br>
> > ^[^    Jaromir<br>
> > <br>
> > Sent from Squeak Inbox Talk<br>
> > <br>
> > On 2021-12-19T18:56:48+01:00, mail at jaromir.net wrote:<br>
> > <br>
> > > Hi Christoph,<br>
> > > <br>
> > > I have tested your test20TerminateProcess and I think the expectations are not set correctly:<br>
> > > <br>
> > > If you run your nice test-block in a workspace<br>
> > > <br>
> > > ����[x := 1.<br>
> > > ����[y := 1.<br>
> > > ����self error: #first.<br>
> > > ����y := 2] ensure:<br>
> > > ��������[z := 1.<br>
> > > ��������self error: #second.<br>
> > > ��������z := 2].<br>
> > > ����x := 2] value<br>
> > > <br>
> > > it answers correctly {x. y. z} = #(1 1 2) for both Abandon and terminate options (if you Abandon or terminate the first error outside the ensure block and Proceed the second error inside the ensure block; there are no unfinished unwind blocks present
 when termination happens and the two mode of termination end identically).<br>
> > > <br>
> > > Please check I understand the test intention correctly (I haven't decoded all the fine details yet but thanks for inspiration!).<br>
> > > <br>
> > > FYI, I've uploaded 4 tests complementing your ones (ToolsTests-jar.109)<br>
> > > <br>
> > > Also, with regard to the latest conversation about multiple terminations / resumptions in
<a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217695.html">
http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217695.html</a> I'd like to ask you to wait with assertions about isTerminated until the issue is resolved. At the moment isTerminated is either not 100% truthful and answers yes during termination
 or is unprotected against multiple termination issue.<br>
> > > <br>
> > > Best,<br>
> > > <br>
> > > <br>
> > > ~~~<br>
> > > ^[^    Jaromir<br>
> > > <br>
> > > Sent from Squeak Inbox Talk<br>
> > > <br>
> > > On 2021-12-16T01:38:57+00:00, commits at source.squeak.org wrote:<br>
> > > <br>
> > > > Christoph Thiede uploaded a new version of ToolsTests to project The Trunk:<br>
> > > > <a href="http://source.squeak.org/trunk/ToolsTests-ct.107.mcz">http://source.squeak.org/trunk/ToolsTests-ct.107.mcz</a><br>
> > > > <br>
> > > > ==================== Summary ====================<br>
> > > > <br>
> > > > Name: ToolsTests-ct.107<br>
> > > > Author: ct<br>
> > > > Time: 16 December 2021, 2:29:44.341664 am<br>
> > > > UUID: 6b771eec-03fe-0a4d-91c9-50480d259573<br>
> > > > Ancestors: ToolsTests-mt.106<br>
> > > > <br>
> > > > Complements Kernel-ct.1434 (revised termination modi on Process). Adds end-to-end tests for abandoning vs. terminating a debugger inside an active unwind context. Makes proper use of new termination modi in clean-ups for other tests.<br>
> > > > <br>
> > > > =============== Diff against ToolsTests-mt.106 ===============<br>
> > > > <br>
> > > > Item was changed:<br>
> > > >   ----- Method: DebuggerTests>>tearDown (in category 'running') -----<br>
> > > >   tearDown<br>
> > > >   <br>
> > > >   ����debugger ifNotNil: [debugger close].<br>
> > > > + ����process ifNotNil: [process terminateAggressively].<br>
> > > > - ����process ifNotNil: [process terminate].<br>
> > > >   ����<br>
> > > >   ����process := nil.<br>
> > > >   ����debugger := nil.<br>
> > > >   ����window := nil.<br>
> > > >   <br>
> > > >   ����reset do: #value.����<br>
> > > >   ����<br>
> > > >   ����super tearDown.!<br>
> > > > <br>
> > > > Item was changed:<br>
> > > >   ----- Method: DebuggerTests>>test16HandleSimulationError (in category 'tests') -----<br>
> > > >   test16HandleSimulationError<br>
> > > >   ����"Regression test. In the past, the scenario below led to an infinite debugger chain freezing your image. Be careful when running this test in an unpatched image!! For more information, see
<a href="http://forum.world.st/I-broke-the-debugger-td5110752.html.%22">http://forum.world.st/I-broke-the-debugger-td5110752.html."</a><br>
> > > >   <br>
> > > >   ����| userProcess |<br>
> > > >   ����process := Process forBlock: [<br>
> > > >   ��������"the faulty user code"<br>
> > > >   ��������thisContext pc: nil].<br>
> > > >   ����debugger := process debug.<br>
> > > >   ����<br>
> > > >   ����[userProcess := [debugger stepThrough] fork.<br>
> > > >   ����Processor yield.<br>
> > > >   ����<br>
> > > >   ����self deny: [process isTerminated].<br>
> > > >   ����self assert: [userProcess isSuspended]]<br>
> > > >   ��������<br>
> > > >   ��������ensure: [<br>
> > > > + ������������process destroy.<br>
> > > > - ������������process suspendedContext: nil; terminate.<br>
> > > >   ������������debugger close.<br>
> > > >   ������������process := userProcess.<br>
> > > >   ������������self findDebugger "for correct tearDown"].!<br>
> > > > <br>
> > > > Item was changed:<br>
> > > >   ----- Method: DebuggerTests>>test17HandleBlockCannotReturn (in category 'tests') -----<br>
> > > >   test17HandleBlockCannotReturn<br>
> > > >   ����"Regression test. In the past, the scenario below led to an infinite debugger chain freezing your image. Be careful when running this test in an unpatched image!! For more information, see
<a href="http://forum.world.st/I-broke-the-debugger-td5110752.html.%22">http://forum.world.st/I-broke-the-debugger-td5110752.html."</a><br>
> > > >   <br>
> > > >   ����| userProcess |<br>
> > > >   ����process := Process forBlock: [<br>
> > > >   ��������"the faulty user code"<br>
> > > >   ��������[] ensure: [thisContext privSender: nil]].<br>
> > > >   ����debugger := process debug.<br>
> > > >   ����<br>
> > > >   ����[userProcess := [debugger stepOver] fork.<br>
> > > >   ����Processor yield.<br>
> > > >   ����<br>
> > > >   ����self assert: [process isTerminated].<br>
> > > >   ����self deny: [userProcess isRunnable]]<br>
> > > >   ��������<br>
> > > >   ��������ensure: [<br>
> > > > + ������������process terminateAggressively.<br>
> > > > - ������������process terminate.<br>
> > > >   ������������debugger close.<br>
> > > >   ������������process := userProcess.<br>
> > > >   ������������self findDebugger "for correct tearDown"].!<br>
> > > > <br>
> > > > Item was changed:<br>
> > > >   ----- Method: DebuggerTests>>test18HandleNestedBlockCannotReturn (in category 'tests') -----<br>
> > > >   test18HandleNestedBlockCannotReturn<br>
> > > >   ����"Regression test. In the past, the scenario below led to an infinite debugger chain freezing your image. Be careful when running this test in an unpatched image!! For more information, see
<a href="http://forum.world.st/I-broke-the-debugger-td5110752.html.%22">http://forum.world.st/I-broke-the-debugger-td5110752.html."</a><br>
> > > >   <br>
> > > >   ����| metaProcess metaDebugger userProcess |<br>
> > > >   ����process := Process forBlock: [<br>
> > > >   ��������"the faulty user code"<br>
> > > >   ��������[] ensure: [thisContext privSender: nil]].<br>
> > > >   ����debugger := process debug.<br>
> > > >   ����metaProcess := Process forBlock: [<br>
> > > >   ��������debugger stepOver].<br>
> > > >   ����metaDebugger := metaProcess debug.<br>
> > > >   ����<br>
> > > >   ����[userProcess := [metaDebugger stepOver] fork.<br>
> > > >   ����Processor yield.<br>
> > > >   ����<br>
> > > >   ����self assert: [process isTerminated].<br>
> > > >   ����self deny: [userProcess isRunnable]]<br>
> > > >   ��������<br>
> > > >   ��������ensure: [<br>
> > > > + ������������process terminateAggressively.<br>
> > > > - ������������process terminate.<br>
> > > >   ������������debugger close.<br>
> > > > + ������������metaProcess terminateAggressively.<br>
> > > > - ������������metaProcess terminate.<br>
> > > >   ������������metaDebugger close.<br>
> > > >   ������������process := userProcess.<br>
> > > >   ������������self findDebugger "for correct tearDown"].!<br>
> > > > <br>
> > > > Item was added:<br>
> > > > + ----- Method: DebuggerTests>>test19Abandon (in category 'tests') -----<br>
> > > > + test19Abandon<br>
> > > > + ����"When the debugger is abandoned, the interrupted process is terminated aggressively, i.e., all not yet started unwind contexts are executed. Further errors that occur during unwinding lead to another debugger showing up. This is the acceptance
 test equivalent for ProcessTest >> #testTerminateNestedUnwindAggressively."<br>
> > > > + <br>
> > > > + ����| x y z userProcess |<br>
> > > > + ����process := Process<br>
> > > > + ��������forBlock:<br>
> > > > + ������������[x := 1.<br>
> > > > + ������������[y := 1.<br>
> > > > + ������������self error: #first.<br>
> > > > + ������������y := 2] ensure:<br>
> > > > + ����������������[z := 1.<br>
> > > > + ����������������self error: #second.<br>
> > > > + ����������������z := 2].<br>
> > > > + ������������x := 2]<br>
> > > > + ��������runUntil: [:ctx | y = 1].<br>
> > > > + ����self should: {x. y. z} = {1. 1. nil}.<br>
> > > > + ����debugger := process debug.<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger proceed] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self deny: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self deny: debugger isNil.<br>
> > > > + ����self assert: {1. 1. nil} equals: {x. y. z}.<br>
> > > > + ����self assert: (debugger containingWindow label includesSubstring: #first).<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger abandon] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self deny: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self deny: debugger isNil.<br>
> > > > + ����self assert: {1. 1. 1} equals: {x. y. z}.<br>
> > > > + ����self assert: (debugger containingWindow label includesSubstring: #second).<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger proceed] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self assert: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self assert: debugger isNil.<br>
> > > > + ����self assert: {1. 1. 2} equals: {x. y. z}.!<br>
> > > > <br>
> > > > Item was added:<br>
> > > > + ----- Method: DebuggerTests>>test20TerminateProcess (in category 'tests') -----<br>
> > > > + test20TerminateProcess<br>
> > > > + ����"When the debugger's process is terminated, all unwind contexts, including already entered ones, are executed. Further errors that occur during unwinding lead to another debugger showing up. This is the acceptance test equivalent for ProcessTest
 >> #testTerminateNestedUnwind."<br>
> > > > + <br>
> > > > + ����| x y z userProcess |<br>
> > > > + ����process := Process<br>
> > > > + ��������forBlock:<br>
> > > > + ������������[x := 1.<br>
> > > > + ������������[y := 1.<br>
> > > > + ������������self error: #first.<br>
> > > > + ������������y := 2] ensure:<br>
> > > > + ����������������[z := 1.<br>
> > > > + ����������������self error: #second.<br>
> > > > + ����������������z := 2].<br>
> > > > + ������������x := 2]<br>
> > > > + ��������runUntil: [:ctx | y = 1].<br>
> > > > + ����self should: {x. y. z} = {1. 1. nil}.<br>
> > > > + ����debugger := process debug.<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger proceed] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self deny: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self deny: debugger isNil.<br>
> > > > + ����self assert: {1. 1. nil} equals: {x. y. z}.<br>
> > > > + ����self assert: (debugger containingWindow label includesSubstring: #first).<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger terminateProcess] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self deny: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self deny: debugger isNil.<br>
> > > > + ����self assert: {1. 2. 1} equals: {x. y. z}.<br>
> > > > + ����self assert: (debugger containingWindow label includesSubstring: #second).<br>
> > > > + ����<br>
> > > > + ����userProcess := [debugger proceed] forkAt: Processor activePriority + 1.<br>
> > > > + ����Processor yield.<br>
> > > > + ����self findDebugger.<br>
> > > > + ����<br>
> > > > + ����self assert: process isTerminated.<br>
> > > > + ����self assert: userProcess isTerminated.<br>
> > > > + ����self assert: debugger isNil.<br>
> > > > + ����self assert: {2. 2. 2} equals: {x. y. z}.!<br>
> > > > <br>
> > > ><br>
> > > <br>
> > ><br>
> > <br>
> > <br>
> -------------- next part --------------<br>
> An HTML attachment was scrubbed...<br>
> URL: <<a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220110/4124c75c/attachment-0001.html">http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220110/4124c75c/attachment-0001.html</a>><br>
> <br>
> <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>