-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpath---mixin-that-memory-leak-3ca758ad07028cff78d0.js.map
1 lines (1 loc) · 66.2 KB
/
path---mixin-that-memory-leak-3ca758ad07028cff78d0.js.map
1
{"version":3,"sources":["webpack:///path---mixin-that-memory-leak-3ca758ad07028cff78d0.js","webpack:///./.cache/json/mixin-that-memory-leak.json"],"names":["webpackJsonp","537","module","exports","data","site","siteMetadata","title","markdownRemark","id","html","frontmatter","date","author","bio","avatar","childImageSharp","resolutions","tracedSVG","width","height","src","srcSet","pathContext","slug","previous","fields","next"],"mappings":"AAAAA,cAAc,iBAERC,IACA,SAAUC,EAAQC,GCHxBD,EAAAC,SAAkBC,MAAQC,MAAQC,cAAgBC,MAAA,4BAAmCC,gBAAmBC,GAAA,0HAAAC,KAAA,6p3BAAml2BC,aAAwmDJ,MAAA,yBAAAK,KAAA,gBAAAC,QAAkEJ,GAAA,aAAAK,IAAA,wHAAAC,QAA0JC,iBAAmBC,aAAeC,UAAA,mnBAAAC,MAAA,GAAAC,OAAA,GAAAC,IAAA,0DAAAC,OAAA,6PAA29BC,aAAgBC,KAAA,yBAAAC,UAA4CC,QAAUF,KAAA,0BAAgCb,aAAgBJ,MAAA,2BAAkCoB,MAASD,QAAUF,KAAA,8BAAoCb,aAAgBJ,MAAA","file":"path---mixin-that-memory-leak-3ca758ad07028cff78d0.js","sourcesContent":["webpackJsonp([175624018417515],{\n\n/***/ 537:\n/***/ (function(module, exports) {\n\n\tmodule.exports = {\"data\":{\"site\":{\"siteMetadata\":{\"title\":\"Engineering at MindLink\"}},\"markdownRemark\":{\"id\":\"/Applications/AzureDevOpsAgent/_work/13/s/src/pages/18-07-05-mixin-the-leak/index.md absPath of file >>> MarkdownRemark\",\"html\":\"<p>This is a story of how, without much effort, mixins can give you memory leaks all over your shiny stuff.</p>\\n<h2>TL;DR</h2>\\n<ul>\\n<li>\\n<p>Mixins <strong>share the properties with their target</strong></p>\\n</li>\\n<li>\\n<p>Conflicts between property names with different semantics can lead to memory leaks or undefined behaviour</p>\\n</li>\\n<li>\\n<p>Ideally don’t use mixins</p>\\n</li>\\n<li>\\n<p>If you have to, either:</p>\\n<ol>\\n<li>Make sure the mixin is using unique property names, or symbols as properties for ‘private’ members</li>\\n<li>Make it clear when a property is accessible to a target and when it isn’t</li>\\n</ol>\\n</li>\\n</ul>\\n<h2>The Story</h2>\\n<p>Performance is important to us, we heavily optimize our clients to get the most out of the browser for fast rendering, we also regularly perform memory profiling to ensure we don’t leak all over the place.</p>\\n<p>After introducing a new implementation of our rich text input (moving away from DraftJS on mobile devices because <a href=\\\"/why-draftjs-doesnt-work-on-android\\\">it doesn’t work properly</a>) I did a quick memory profiling session over it and found just what I hoped I wouldn’t - a leak all over our nice new input.</p>\\n<p>The problem is that leak wasn’t in the new code, it was old… We missed it. We need to get better at making sure we don’t miss it in future, that’s a journey we’re taking.</p>\\n<p>The memory snapshot showing the leak looks like this:</p>\\n<p>\\n <a\\n class=\\\"gatsby-resp-image-link\\\"\\n href=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-0a6eb.jpg\\\"\\n style=\\\"display: block\\\"\\n target=\\\"_blank\\\"\\n rel=\\\"noopener\\\"\\n >\\n \\n <span\\n class=\\\"gatsby-resp-image-wrapper\\\"\\n style=\\\"position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;\\\"\\n >\\n <span\\n class=\\\"gatsby-resp-image-background-image\\\"\\n style=\\\"padding-bottom: 42.90865384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB2m5JUMP/xAAXEAADAQAAAAAAAAAAAAAAAAAAARAR/9oACAEBAAEFAsMjjP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAAAAg4f/aAAgBAQAGPwIq/wD/xAAbEAACAgMBAAAAAAAAAAAAAAAAATFBEVGRcf/aAAgBAQABPyFe+mOg0k76SZRM/9oADAMBAAIAAwAAABDU/wD/xAAWEQADAAAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QiIj/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAECAQE/EK8Kz//EABwQAAMAAQUAAAAAAAAAAAAAAAABEZEQMVGBsf/aAAgBAQABPxBVmFj5uRMRO+gW08T/2Q=='); background-size: cover; display: block;\\\"\\n >\\n <img\\n class=\\\"gatsby-resp-image-image\\\"\\n style=\\\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\\\"\\n alt=\\\"The leak itself\\\"\\n title=\\\"\\\"\\n src=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-f8fb9.jpg\\\"\\n srcset=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-e8976.jpg 148w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-63df2.jpg 295w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-f8fb9.jpg 590w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-0a6eb.jpg 832w\\\"\\n sizes=\\\"(max-width: 590px) 100vw, 590px\\\"\\n />\\n </span>\\n </span>\\n \\n </a>\\n </p>\\n<p>That event handler <code class=\\\"language-text\\\">"interactivitychanged"</code> on the <code class=\\\"language-text\\\">InteractivityMonitor</code> shouldn’t be there, it should have been removed as part of the destruction of the view model.</p>\\n<p>My first instinct was that this must be because we’re just not destroying the view model at all. A quick debug later, nope that’s not it.</p>\\n<p>Next on the list is that we may be destroying it, but is that actually cleaning up the event handlers? Yes, yes it is…</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n<span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span> <span class=\\\"token comment\\\">// <-- Yupp we're removing the listener.</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n<span class=\\\"token punctuation\\\">}</span></code></pre>\\n </div>\\n<p>So what’s going on? The debug session showed that the <code class=\\\"language-text\\\">InteractivityMonitor</code> that we’re cleaning up has no registered handlers, but the memory profiler is definitive in its report that there is one there…</p>\\n<p>That means we’re looking at different instances of the same type and so the answer lies in who we add the listener to and remove the listener from.</p>\\n<p>Let’s start from the leaky view model:</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Represents an interface for the constructor configuration.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">interface</span> <span class=\\\"token class-name\\\">IComposeMessageInputViewModelConfig</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n \\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token comment\\\">/**\\n * Represents the view model for a compose message input view.\\n */</span>\\n<span class=\\\"token keyword\\\">class</span> <span class=\\\"token class-name\\\">ComposeMessageInputViewModel</span> <span class=\\\"token keyword\\\">extends</span> <span class=\\\"token class-name\\\">FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>MessageInputViewModel</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * Initializes the interactable mixin.\\n *\\n * @param config The configuration object.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> initializeInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IInteractableConfig<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> destroyInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> interactivityMonitor<span class=\\\"token punctuation\\\">:</span> FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Initializes a new instance of this class.\\n *\\n * @param config The initial configuration.\\n */</span>\\n <span class=\\\"token keyword\\\">constructor</span><span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IComposeMessageInputViewModelConfig<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">super</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">initializeInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">{</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> config<span class=\\\"token punctuation\\\">.</span>interactivityMonitor\\n <span class=\\\"token punctuation\\\">}</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys this instance.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n \\n <span class=\\\"token keyword\\\">super</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Updates the interactivity monitor following a change in active conversation.\\n *\\n * @param interactivityMonitor The interactivity monitor for the conversation.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> <span class=\\\"token function\\\">updateInteractivityMonitor</span><span class=\\\"token punctuation\\\">(</span>interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">if</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor <span class=\\\"token operator\\\">=</span> interactivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">on</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleMessageSendabilityChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token function\\\">mixin</span><span class=\\\"token punctuation\\\">(</span>ComposeMessageInputViewModel<span class=\\\"token punctuation\\\">,</span> Interactable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">default</span> ComposeMessageInputViewModel<span class=\\\"token punctuation\\\">;</span></code></pre>\\n </div>\\n<p>We see that he mixes in an <code class=\\\"language-text\\\">Interactable</code>. The view model himself adds and removes a listener symmetrically, so that’s fine. He does have an interactivity monitor and through his lifetime changes it based on the conversation it represents, but that’s used for something else, not listening on the leaky event.</p>\\n<p>Enter the <code class=\\\"language-text\\\">Interactable</code> mixin.</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Represents an interface for the constructor configuration.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">interface</span> <span class=\\\"token class-name\\\">IInteractableConfig</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token comment\\\">/**\\n * Represents a simple mixin that determines whether the view model is interactable.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">default</span> <span class=\\\"token keyword\\\">class</span> <span class=\\\"token class-name\\\">Interactable</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor <span class=\\\"token operator\\\">=</span> <span class=\\\"token keyword\\\">null</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Sets whether the property is interactable or not.\\n *\\n * @param name The property name.\\n * @param value Whether the property is interactable or not.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> setProperty<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">,</span> value<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Gets whether the property is interactable or not.\\n *\\n * @param name The property name.\\n * @returns `true` if the property is interactable, `false` otherwise.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> getProperty<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Add properties.\\n *\\n * @param name The property name.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> addProperties<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Initializes the interactable mixin.\\n *\\n * @param config The initial configuration.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">initializeInteractable</span><span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IInteractableConfig<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">addProperties</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">{</span>\\n isInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token boolean\\\">false</span>\\n <span class=\\\"token punctuation\\\">}</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor <span class=\\\"token operator\\\">=</span> config<span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">on</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">isInteractive</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Handles when the interactable state changes.\\n *\\n * @param _ The new interactable state.\\n */</span>\\n <span class=\\\"token keyword\\\">protected</span> <span class=\\\"token function\\\">handleInteractableChanged</span><span class=\\\"token punctuation\\\">(</span>_<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Handles when the interactable state of the monitor changes.\\n *\\n * @param _ The interactivity monitor.\\n * @param isInteractive The new interactable state.\\n */</span>\\n <span class=\\\"token keyword\\\">protected</span> <span class=\\\"token function\\\">handleInteractivityMonitorChanged</span><span class=\\\"token punctuation\\\">(</span>_<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">,</span> isInteractive<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span>isInteractive<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Gets a value indicating whether the view model is interactable.\\n *\\n * @returns `true` if the view model is interactable, `false` otherwise.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">getIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getProperty</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"isInteractable\\\"</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Sets whether the view model is interactable.\\n *\\n * @param isInteractable Whether the view model is interactable.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> <span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span>isInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">if</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">===</span> isInteractable<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setProperty</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"isInteractable\\\"</span><span class=\\\"token punctuation\\\">,</span> isInteractable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">handleInteractableChanged</span><span class=\\\"token punctuation\\\">(</span>isInteractable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n<span class=\\\"token punctuation\\\">}</span></code></pre>\\n </div>\\n<p>Looking at him he seems all fine and dandy - initializing adds the listener, destroying removes it. Great, no problem here…</p>\\n<p>…</p>\\n<p>Hold on… What’s that right there? Can you see it? The damn interactivity monitor property has the same name in the mixin as in the view model! That’s a problem.</p>\\n<p>When we mix something in what we’re actually doing is <em>copying</em> implementation from the mixin to the target. There’s only a single instance with both the mixin and target properties, that means that things with the same name in both types refer to <strong>the same thing</strong>.</p>\\n<p>What’s happening here is that the <code class=\\\"language-text\\\">Interactable</code> mixin is adding the event listener to the initial instance of the interactivity monitor, then during its lifetime the view model is assigning to itself a new interactivity monitor. By the time the <code class=\\\"language-text\\\">Interactable</code> is asked to clean up, the shared property is referring to a different instance and the event listener is still on the old instance that we no longer have a reference to! LEAK! We have found you and now we have to patch you up!</p>\\n<p>The proper way to do this is to stop using mixins, they really aren’t great for a number of reasons - this is just one of them. However, that’s quite a big change that we will schedule for another time. For now we can avoid this issue by renaming the mixin property so that it’s unique (though there’s no guarantee unless we use symbols for properties).</p>\\n<p>With the property renamed the leak is gone :)</p>\",\"frontmatter\":{\"title\":\"Mixin that memory leak\",\"date\":\"July 05, 2018\",\"author\":{\"id\":\"Luke Terry\",\"bio\":\"Senior Engineer at MindLink. Enjoys technology, playing games and making things work, blogs at www.indescrible.co.uk.\",\"avatar\":{\"childImageSharp\":{\"resolutions\":{\"tracedSVG\":\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60' version='1'%3E%3Crect width='100%25' height='100%25' fill='%23f6f2f8'/%3E%3Cpath d='M0 4l1 4v17l-1 8 1 7 1 2-1 1-1 9v8h11c11 0 11 0 11-2l-2-9c0-6 0-6 2-5l5 1 4-1h-4c-4 0-8-5-11-12-2-6-3-9-1-9 4 0 5 0 4-1l-2-1c-1 1-2 0-2-2-1-4 2-9 5-10l12 1 3 1c1-1 2 2 2 3l1 5c2 4 2 4 2 2 0-3 0-3 2-1s-1 12-3 9l-1 2c0 3-5 11-7 12v1l4-3 3-4 4 4c5 6 8 13 9 18l5 1h5V34a171 171 0 0 0-1-27l1-3V0H0v4m0 12c0 3 1 4 1 2v-6c-1-1-1 0-1 4m0 17c0 4 1 6 1 3v-8l-1 5m0 21c0 4 1 5 1 3v-6c0-2-1-1-1 3' fill='%23e0d6eb' fill-rule='evenodd'/%3E%3C/svg%3E\",\"width\":60,\"height\":60,\"src\":\"/static/luke-b4696583a30eac95175e7eb6a8becde1-454f9.jpg\",\"srcSet\":\"/static/luke-b4696583a30eac95175e7eb6a8becde1-454f9.jpg 1x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-f8c68.jpg 1.5x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-d364e.jpg 2x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-e5a4b.jpg 3x\"}}}}}}},\"pathContext\":{\"slug\":\"mixin-that-memory-leak\",\"previous\":{\"fields\":{\"slug\":\"improving-our-ci-tests\"},\"frontmatter\":{\"title\":\"Improving our CI tests\"}},\"next\":{\"fields\":{\"slug\":\"parallelizing-our-ci-tests\"},\"frontmatter\":{\"title\":\"Parallelizing our CI tests\"}}}}\n\n/***/ })\n\n});\n\n\n// WEBPACK FOOTER //\n// path---mixin-that-memory-leak-3ca758ad07028cff78d0.js","module.exports = {\"data\":{\"site\":{\"siteMetadata\":{\"title\":\"Engineering at MindLink\"}},\"markdownRemark\":{\"id\":\"/Applications/AzureDevOpsAgent/_work/13/s/src/pages/18-07-05-mixin-the-leak/index.md absPath of file >>> MarkdownRemark\",\"html\":\"<p>This is a story of how, without much effort, mixins can give you memory leaks all over your shiny stuff.</p>\\n<h2>TL;DR</h2>\\n<ul>\\n<li>\\n<p>Mixins <strong>share the properties with their target</strong></p>\\n</li>\\n<li>\\n<p>Conflicts between property names with different semantics can lead to memory leaks or undefined behaviour</p>\\n</li>\\n<li>\\n<p>Ideally don’t use mixins</p>\\n</li>\\n<li>\\n<p>If you have to, either:</p>\\n<ol>\\n<li>Make sure the mixin is using unique property names, or symbols as properties for ‘private’ members</li>\\n<li>Make it clear when a property is accessible to a target and when it isn’t</li>\\n</ol>\\n</li>\\n</ul>\\n<h2>The Story</h2>\\n<p>Performance is important to us, we heavily optimize our clients to get the most out of the browser for fast rendering, we also regularly perform memory profiling to ensure we don’t leak all over the place.</p>\\n<p>After introducing a new implementation of our rich text input (moving away from DraftJS on mobile devices because <a href=\\\"/why-draftjs-doesnt-work-on-android\\\">it doesn’t work properly</a>) I did a quick memory profiling session over it and found just what I hoped I wouldn’t - a leak all over our nice new input.</p>\\n<p>The problem is that leak wasn’t in the new code, it was old… We missed it. We need to get better at making sure we don’t miss it in future, that’s a journey we’re taking.</p>\\n<p>The memory snapshot showing the leak looks like this:</p>\\n<p>\\n <a\\n class=\\\"gatsby-resp-image-link\\\"\\n href=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-0a6eb.jpg\\\"\\n style=\\\"display: block\\\"\\n target=\\\"_blank\\\"\\n rel=\\\"noopener\\\"\\n >\\n \\n <span\\n class=\\\"gatsby-resp-image-wrapper\\\"\\n style=\\\"position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;\\\"\\n >\\n <span\\n class=\\\"gatsby-resp-image-background-image\\\"\\n style=\\\"padding-bottom: 42.90865384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB2m5JUMP/xAAXEAADAQAAAAAAAAAAAAAAAAAAARAR/9oACAEBAAEFAsMjjP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAAAAg4f/aAAgBAQAGPwIq/wD/xAAbEAACAgMBAAAAAAAAAAAAAAAAATFBEVGRcf/aAAgBAQABPyFe+mOg0k76SZRM/9oADAMBAAIAAwAAABDU/wD/xAAWEQADAAAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QiIj/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREx/9oACAECAQE/EK8Kz//EABwQAAMAAQUAAAAAAAAAAAAAAAABEZEQMVGBsf/aAAgBAQABPxBVmFj5uRMRO+gW08T/2Q=='); background-size: cover; display: block;\\\"\\n >\\n <img\\n class=\\\"gatsby-resp-image-image\\\"\\n style=\\\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\\\"\\n alt=\\\"The leak itself\\\"\\n title=\\\"\\\"\\n src=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-f8fb9.jpg\\\"\\n srcset=\\\"/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-e8976.jpg 148w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-63df2.jpg 295w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-f8fb9.jpg 590w,\\n/static/the-leak-b24b251c7680bea9bcd83642a9000b7a-0a6eb.jpg 832w\\\"\\n sizes=\\\"(max-width: 590px) 100vw, 590px\\\"\\n />\\n </span>\\n </span>\\n \\n </a>\\n </p>\\n<p>That event handler <code class=\\\"language-text\\\">"interactivitychanged"</code> on the <code class=\\\"language-text\\\">InteractivityMonitor</code> shouldn’t be there, it should have been removed as part of the destruction of the view model.</p>\\n<p>My first instinct was that this must be because we’re just not destroying the view model at all. A quick debug later, nope that’s not it.</p>\\n<p>Next on the list is that we may be destroying it, but is that actually cleaning up the event handlers? Yes, yes it is…</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n<span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span> <span class=\\\"token comment\\\">// <-- Yupp we're removing the listener.</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n<span class=\\\"token punctuation\\\">}</span></code></pre>\\n </div>\\n<p>So what’s going on? The debug session showed that the <code class=\\\"language-text\\\">InteractivityMonitor</code> that we’re cleaning up has no registered handlers, but the memory profiler is definitive in its report that there is one there…</p>\\n<p>That means we’re looking at different instances of the same type and so the answer lies in who we add the listener to and remove the listener from.</p>\\n<p>Let’s start from the leaky view model:</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Represents an interface for the constructor configuration.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">interface</span> <span class=\\\"token class-name\\\">IComposeMessageInputViewModelConfig</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n \\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token comment\\\">/**\\n * Represents the view model for a compose message input view.\\n */</span>\\n<span class=\\\"token keyword\\\">class</span> <span class=\\\"token class-name\\\">ComposeMessageInputViewModel</span> <span class=\\\"token keyword\\\">extends</span> <span class=\\\"token class-name\\\">FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>MessageInputViewModel</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * Initializes the interactable mixin.\\n *\\n * @param config The configuration object.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> initializeInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IInteractableConfig<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> destroyInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> interactivityMonitor<span class=\\\"token punctuation\\\">:</span> FcfJS<span class=\\\"token punctuation\\\">.</span>viewmodel<span class=\\\"token punctuation\\\">.</span>AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Initializes a new instance of this class.\\n *\\n * @param config The initial configuration.\\n */</span>\\n <span class=\\\"token keyword\\\">constructor</span><span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IComposeMessageInputViewModelConfig<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">super</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">initializeInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">{</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> config<span class=\\\"token punctuation\\\">.</span>interactivityMonitor\\n <span class=\\\"token punctuation\\\">}</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys this instance.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n \\n <span class=\\\"token keyword\\\">super</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/** -snip- **/</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Updates the interactivity monitor following a change in active conversation.\\n *\\n * @param interactivityMonitor The interactivity monitor for the conversation.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> <span class=\\\"token function\\\">updateInteractivityMonitor</span><span class=\\\"token punctuation\\\">(</span>interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">if</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor <span class=\\\"token operator\\\">=</span> interactivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getInteractivityChangedEvent</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">on</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleMessageSendabilityChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token function\\\">mixin</span><span class=\\\"token punctuation\\\">(</span>ComposeMessageInputViewModel<span class=\\\"token punctuation\\\">,</span> Interactable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">default</span> ComposeMessageInputViewModel<span class=\\\"token punctuation\\\">;</span></code></pre>\\n </div>\\n<p>We see that he mixes in an <code class=\\\"language-text\\\">Interactable</code>. The view model himself adds and removes a listener symmetrically, so that’s fine. He does have an interactivity monitor and through his lifetime changes it based on the conversation it represents, but that’s used for something else, not listening on the leaky event.</p>\\n<p>Enter the <code class=\\\"language-text\\\">Interactable</code> mixin.</p>\\n<div class=\\\"gatsby-highlight\\\">\\n <pre class=\\\"language-typescript\\\"><code class=\\\"language-typescript\\\"><span class=\\\"token comment\\\">/**\\n * Represents an interface for the constructor configuration.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">interface</span> <span class=\\\"token class-name\\\">IInteractableConfig</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n<span class=\\\"token punctuation\\\">}</span>\\n\\n<span class=\\\"token comment\\\">/**\\n * Represents a simple mixin that determines whether the view model is interactable.\\n */</span>\\n<span class=\\\"token keyword\\\">export</span> <span class=\\\"token keyword\\\">default</span> <span class=\\\"token keyword\\\">class</span> <span class=\\\"token class-name\\\">Interactable</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token comment\\\">/**\\n * The interactivity monitor.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> interactivityMonitor<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor <span class=\\\"token operator\\\">=</span> <span class=\\\"token keyword\\\">null</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Sets whether the property is interactable or not.\\n *\\n * @param name The property name.\\n * @param value Whether the property is interactable or not.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> setProperty<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">,</span> value<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Gets whether the property is interactable or not.\\n *\\n * @param name The property name.\\n * @returns `true` if the property is interactable, `false` otherwise.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> getProperty<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Add properties.\\n *\\n * @param name The property name.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> addProperties<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token punctuation\\\">(</span>name<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">any</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">=></span> <span class=\\\"token keyword\\\">void</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Initializes the interactable mixin.\\n *\\n * @param config The initial configuration.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">initializeInteractable</span><span class=\\\"token punctuation\\\">(</span>config<span class=\\\"token punctuation\\\">:</span> IInteractableConfig<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">addProperties</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">{</span>\\n isInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token boolean\\\">false</span>\\n <span class=\\\"token punctuation\\\">}</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor <span class=\\\"token operator\\\">=</span> config<span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">on</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">isInteractive</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Destroys the interactable mixin.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">destroyInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">un</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"interactivitychanged\\\"</span><span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>handleInteractivityMonitorChanged<span class=\\\"token punctuation\\\">,</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span>interactivityMonitor<span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">destroy</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Handles when the interactable state changes.\\n *\\n * @param _ The new interactable state.\\n */</span>\\n <span class=\\\"token keyword\\\">protected</span> <span class=\\\"token function\\\">handleInteractableChanged</span><span class=\\\"token punctuation\\\">(</span>_<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Handles when the interactable state of the monitor changes.\\n *\\n * @param _ The interactivity monitor.\\n * @param isInteractive The new interactable state.\\n */</span>\\n <span class=\\\"token keyword\\\">protected</span> <span class=\\\"token function\\\">handleInteractivityMonitorChanged</span><span class=\\\"token punctuation\\\">(</span>_<span class=\\\"token punctuation\\\">:</span> AbstractInteractivityMonitor<span class=\\\"token punctuation\\\">,</span> isInteractive<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span>isInteractive<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Gets a value indicating whether the view model is interactable.\\n *\\n * @returns `true` if the view model is interactable, `false` otherwise.\\n */</span>\\n <span class=\\\"token keyword\\\">public</span> <span class=\\\"token function\\\">getIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span> <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getProperty</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"isInteractable\\\"</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token comment\\\">/**\\n * Sets whether the view model is interactable.\\n *\\n * @param isInteractable Whether the view model is interactable.\\n */</span>\\n <span class=\\\"token keyword\\\">private</span> <span class=\\\"token function\\\">setIsInteractable</span><span class=\\\"token punctuation\\\">(</span>isInteractable<span class=\\\"token punctuation\\\">:</span> <span class=\\\"token builtin\\\">boolean</span><span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">:</span> <span class=\\\"token keyword\\\">void</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">if</span> <span class=\\\"token punctuation\\\">(</span><span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">getIsInteractable</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token punctuation\\\">)</span> <span class=\\\"token operator\\\">===</span> isInteractable<span class=\\\"token punctuation\\\">)</span> <span class=\\\"token punctuation\\\">{</span>\\n <span class=\\\"token keyword\\\">return</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">setProperty</span><span class=\\\"token punctuation\\\">(</span><span class=\\\"token string\\\">\\\"isInteractable\\\"</span><span class=\\\"token punctuation\\\">,</span> isInteractable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token keyword\\\">this</span><span class=\\\"token punctuation\\\">.</span><span class=\\\"token function\\\">handleInteractableChanged</span><span class=\\\"token punctuation\\\">(</span>isInteractable<span class=\\\"token punctuation\\\">)</span><span class=\\\"token punctuation\\\">;</span>\\n <span class=\\\"token punctuation\\\">}</span>\\n<span class=\\\"token punctuation\\\">}</span></code></pre>\\n </div>\\n<p>Looking at him he seems all fine and dandy - initializing adds the listener, destroying removes it. Great, no problem here…</p>\\n<p>…</p>\\n<p>Hold on… What’s that right there? Can you see it? The damn interactivity monitor property has the same name in the mixin as in the view model! That’s a problem.</p>\\n<p>When we mix something in what we’re actually doing is <em>copying</em> implementation from the mixin to the target. There’s only a single instance with both the mixin and target properties, that means that things with the same name in both types refer to <strong>the same thing</strong>.</p>\\n<p>What’s happening here is that the <code class=\\\"language-text\\\">Interactable</code> mixin is adding the event listener to the initial instance of the interactivity monitor, then during its lifetime the view model is assigning to itself a new interactivity monitor. By the time the <code class=\\\"language-text\\\">Interactable</code> is asked to clean up, the shared property is referring to a different instance and the event listener is still on the old instance that we no longer have a reference to! LEAK! We have found you and now we have to patch you up!</p>\\n<p>The proper way to do this is to stop using mixins, they really aren’t great for a number of reasons - this is just one of them. However, that’s quite a big change that we will schedule for another time. For now we can avoid this issue by renaming the mixin property so that it’s unique (though there’s no guarantee unless we use symbols for properties).</p>\\n<p>With the property renamed the leak is gone :)</p>\",\"frontmatter\":{\"title\":\"Mixin that memory leak\",\"date\":\"July 05, 2018\",\"author\":{\"id\":\"Luke Terry\",\"bio\":\"Senior Engineer at MindLink. Enjoys technology, playing games and making things work, blogs at www.indescrible.co.uk.\",\"avatar\":{\"childImageSharp\":{\"resolutions\":{\"tracedSVG\":\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60' version='1'%3E%3Crect width='100%25' height='100%25' fill='%23f6f2f8'/%3E%3Cpath d='M0 4l1 4v17l-1 8 1 7 1 2-1 1-1 9v8h11c11 0 11 0 11-2l-2-9c0-6 0-6 2-5l5 1 4-1h-4c-4 0-8-5-11-12-2-6-3-9-1-9 4 0 5 0 4-1l-2-1c-1 1-2 0-2-2-1-4 2-9 5-10l12 1 3 1c1-1 2 2 2 3l1 5c2 4 2 4 2 2 0-3 0-3 2-1s-1 12-3 9l-1 2c0 3-5 11-7 12v1l4-3 3-4 4 4c5 6 8 13 9 18l5 1h5V34a171 171 0 0 0-1-27l1-3V0H0v4m0 12c0 3 1 4 1 2v-6c-1-1-1 0-1 4m0 17c0 4 1 6 1 3v-8l-1 5m0 21c0 4 1 5 1 3v-6c0-2-1-1-1 3' fill='%23e0d6eb' fill-rule='evenodd'/%3E%3C/svg%3E\",\"width\":60,\"height\":60,\"src\":\"/static/luke-b4696583a30eac95175e7eb6a8becde1-454f9.jpg\",\"srcSet\":\"/static/luke-b4696583a30eac95175e7eb6a8becde1-454f9.jpg 1x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-f8c68.jpg 1.5x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-d364e.jpg 2x,\\n/static/luke-b4696583a30eac95175e7eb6a8becde1-e5a4b.jpg 3x\"}}}}}}},\"pathContext\":{\"slug\":\"mixin-that-memory-leak\",\"previous\":{\"fields\":{\"slug\":\"improving-our-ci-tests\"},\"frontmatter\":{\"title\":\"Improving our CI tests\"}},\"next\":{\"fields\":{\"slug\":\"parallelizing-our-ci-tests\"},\"frontmatter\":{\"title\":\"Parallelizing our CI tests\"}}}}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/json-loader!./.cache/json/mixin-that-memory-leak.json\n// module id = 537\n// module chunks = 175624018417515"],"sourceRoot":""}