Hi. I am not sure if I understand which is the bug and it is difficult to do a clear diff. You mean that weak references should NOT be serialized ?  While thinking about this in Fuel<a href="http://forum.world.st/Should-a-serializer-do-something-in-particular-with-weak-references-td3827593.html"> I asked in the mailing list</a> and the conclusion was that we shouldn&#39;t do anything special in Fuel for weak references. In this case, if I understand, you are saying the opposite: do something different for weak references, basically to consider them &quot;transient&quot;. Can you please explain me why it is needed a specific behavior for weak references? <br>
<br>Thanks in advance!<br><br><br><div class="gmail_quote">On Sun, Nov 27, 2011 at 6:28 PM, Juan Vuletich <span dir="ltr">&lt;<a href="mailto:juan@jvuletich.org">juan@jvuletich.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi Folks,<br>
<br>
I found a bug in Cuis that made weak references to be improperly dumped in SmartRefStreams due to a bug in ReferenceStream. When I tried to reproduce the bug and fix in Squeak, I found out that in Squeak weak references are always dumped (and not just the more subtle bug in Cuis). The attach includes a test and fix. I&#39;m confident about the fix in the context of Cuis, but I only played a few minutes with this in Squeak.<br>

<br>
Can anybody check this for Squeak and consider it for inclusion?<br>
<br>
Thanks,<span class="HOEnZb"><font color="#888888"><br>
Juan Vuletich<br>
</font></span><br>&#39;From Squeak4.2 of 20 November 2011 [latest update: #11796] on 27 November 2011 at 2:56:53 pm&#39;!<br>
TestCase subclass: #ReferenceStreamTest<br>
        instanceVariableNames: &#39;&#39;<br>
        classVariableNames: &#39;&#39;<br>
        poolDictionaries: &#39;&#39;<br>
        category: &#39;System-Object Storage-Tests&#39;!<br>
<br>
!Object methodsFor: &#39;objects from disk&#39; stamp: &#39;jmv 11/27/2011 14:56&#39;!<br>
storeDataOn: aDataStream<br>
        &quot;Store myself on a DataStream.  Answer self.  This is a low-level DataStream/ReferenceStream method. See also objectToStoreOnDataStream.  NOTE: This method must send &#39;aDataStream beginInstance:size:&#39; and then (nextPut:/nextPutWeak:) its subobjects.  readDataFrom:size: reads back what we write here.&quot;<br>

        | cntInstVars cntIndexedVars |<br>
<br>
        cntInstVars := self class instSize.<br>
        cntIndexedVars := self basicSize.<br>
        aDataStream<br>
                beginInstance: self class<br>
                size: cntInstVars + cntIndexedVars.<br>
        1 to: cntInstVars do:<br>
                [:i | aDataStream nextPut: (self instVarAt: i)].<br>
<br>
        &quot;Write fields of a variable length object.  When writing to a dummy<br>
                stream, don&#39;t bother to write the bytes&quot;<br>
        ((aDataStream byteStream class == DummyStream) and: [self class isBits]) ifFalse: [<br>
                self class isWeak<br>
                        ifTrue: [<br>
                                &quot;For weak classes (for example DependentsArray) write the referenced object only<br>
                                if referenced from elsewhere in the dumped object graph.<br>
                                This means, for instance that if we only dump a model, no dependents are stored,<br>
                                but if we store a view (i.e. a Morph), it is properly handled as a dependent after the object graph is revived.&quot;<br>
                                1 to: cntIndexedVars do: [ :i |<br>
                                        aDataStream nextPutWeak: (self basicAt: i)]]<br>
                        ifFalse: [<br>
                                1 to: cntIndexedVars do: [ :i |<br>
                                        aDataStream nextPut: (self basicAt: i)]]]! !<br>
<br>
<br>
!DiskProxy methodsFor: &#39;i/o&#39; stamp: &#39;jmv 11/25/2011 13:20&#39;!<br>
storeDataOn: aReferenceStream<br>
        &quot;Besides just storing, get me inserted into references, so structures will know about class DiskProxy.&quot;<br>
<br>
        super storeDataOn: aReferenceStream.<br>
<br>
        &quot;just so instVarInfo: will find it and put it into structures&quot;<br>
&quot;       aReferenceStream references at: self put: #none.&quot;<br>
        aReferenceStream addSpecialReference: self! !<br>
<br>
<br>
!ReferenceStream methodsFor: &#39;statistics&#39; stamp: &#39;jmv 11/25/2011 13:21&#39;!<br>
statisticsOfRefs<br>
        &quot;Analyze the information in references, the objects being written out&quot;<br>
<br>
        | parents ownerBags tallies n nm owners normalReferences |<br>
        normalReferences := self references.    &quot;Exclude unrealized weaks&quot;<br>
        parents := IdentityDictionary new: normalReferences size * 2.<br>
        n := 0.<br>
        &#39;Finding Owners...&#39;<br>
        displayProgressFrom: 0 to: normalReferences size<br>
        during: [:bar |<br>
        normalReferences keysDo:<br>
                [:parent | | kids |<br>
                bar value: (n := n+1).<br>
                kids := parent class isFixed<br>
                        ifTrue: [(1 to: parent class instSize) collect: [:i | parent instVarAt: i]]<br>
                        ifFalse: [parent class isBits ifTrue: [Array new]<br>
                                         ifFalse: [(1 to: parent basicSize) collect: [:i | parent basicAt: i]]].<br>
                (kids select: [:x | normalReferences includesKey: x])<br>
                        do: [:child | parents at: child put: parent]]].<br>
        ownerBags := Dictionary new.<br>
        tallies := Bag new.<br>
        n := 0.<br>
        &#39;Tallying Owners...&#39;<br>
        displayProgressFrom: 0 to: normalReferences size<br>
        during: [:bar |<br>
        normalReferences keysDo:  &quot;For each class of obj, tally a bag of owner classes&quot;<br>
                [:obj | | objParent | bar value: (n := n+1).<br>
                nm := obj class name.<br>
                tallies add: nm.<br>
                owners := ownerBags at: nm ifAbsent: [ownerBags at: nm put: Bag new].<br>
                (objParent := parents at: obj ifAbsent: [nil]) == nil<br>
                        ifFalse: [owners add: objParent class name]]].<br>
        ^ String streamContents:<br>
                [:strm |  tallies sortedCounts do:<br>
                        [:assn | n := assn key.  nm := assn value.<br>
                        owners := ownerBags at: nm.<br>
                        strm cr; nextPutAll: nm; space; print: n.<br>
                        owners size &gt; 0 ifTrue:<br>
                                [strm cr; tab; print: owners sortedCounts]]]! !<br>
<br>
!ReferenceStream methodsFor: &#39;writing&#39; stamp: &#39;jmv 11/25/2011 13:20&#39;!<br>
addSpecialReference: aDiskProxy<br>
        &quot;See senders. Added to avoid breaking encapsulation (assuming that #references would answer the actual collection)&quot;<br>
        references at: aDiskProxy put: #none! !<br>
<br>
!ReferenceStream methodsFor: &#39;writing&#39; stamp: &#39;jmv 11/27/2011 14:56&#39;!<br>
references<br>
        &quot;Do not include provisory references created in #nextPutWeak that never became normal references,<br>
        because the referenced object was never added from a call to #nextPut:&quot;<br>
        ^ references select: [ :value | value isNumber ]! !<br>
<br>
<br>
!ReferenceStreamTest methodsFor: &#39;testing&#39; stamp: &#39;jmv 11/27/2011 14:56&#39;!<br>
testWeakDumps<br>
        &quot;Test that if we serialize a model with weak references to views, only the model is serialized and not the views.<br>
<br>
        Note: The bug became apparent only when dumping a model to a SmartRefStream, that calls #references, and the serialized stream<br>
        was later materialized in an image where the view classes had been deleted. In such rare cases, materialization would fail when trying to reference these<br>
        absent classes. If serializing to a ReferenceStream, the bug didn&#39;t become apparent (views were never serialized). If serializing to a SmartRefStream, but<br>
        view classes still existed, the bug didn&#39;t really become apparent (because views were not actually deserialized), the only effect was a larger file.<br>
<br>
        ReferenceStreamTest new testWeakDumps<br>
        &quot;<br>
        | oldInstance refStream |<br>
        oldInstance :=StringHolder new contents: &#39;This is a text&#39;.<br>
        oldInstance addDependent: Morph new.<br>
        refStream := ReferenceStream on: (DummyStream on: nil).<br>
        refStream nextPut: oldInstance.<br>
        self deny: (refStream references keys anySatisfy: [ :dumpedObject | dumpedObject isKindOf: Morph ])! !<br>
<br>
<br><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>