Skip to content

Commit

Permalink
Merge pull request #344 from canjs/cc-leak
Browse files Browse the repository at this point in the history
Prevent leak caused by connectedCallback setup code
  • Loading branch information
matthewp authored May 7, 2019
2 parents e59fc5f + 69baf49 commit 83ecafc
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
48 changes: 48 additions & 0 deletions benchmark/memory3.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!doctype html>
<html lang="en">
<title>Memory tests</title>
<style>
body {
font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

button {
font-size: 200%;
background: salmon;
border: 2px solid black;
color: black;
padding: .5em 1em;
cursor: pointer;
}

#runner {
text-align: center;
}
</style>
<h1>connectedCallback memory leak</h1>
<p>This tests a leak in using ViewModel#connectedCallback when the element is never inserted into the page. Use the devtools memory tool and click <strong>run me</strong>. Every time you click run a new component is created. Hopefully there are no leaks.</p>
<div id="runner">
<button type="button">Run me</button>
</div>
<div id="root"></div>
<script src="../node_modules/steal/steal.js"></script>
<script type="steal-module">
var Component = require("can-component");
var nodeLists = require("can-view-nodelist");

var MyComponent = Component.extend({
tag: "my-thing",
view: "Hello world",
ViewModel: {
// Any connectedCallback will do, just the existence causes a leak.
connectedCallback: function(){}
}
});

function run() {
var inst = new MyComponent();
nodeLists.unregister(inst.nodeList);
}

document.querySelector('button').addEventListener('click', run);
</script>
8 changes: 7 additions & 1 deletion can-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ var Component = Construct.extend(
betweenTagsView = componentTagData.subtemplate || el.ownerDocument.createDocumentFragment.bind(el.ownerDocument);
}
var viewModelDisconnectedCallback,
insertionDisposal,
componentInPage,
nodeRemoved;

Expand All @@ -656,6 +657,10 @@ var Component = Construct.extend(
} else if(typeof viewModel.stopListening === "function"){
viewModel.stopListening();
}
if(insertionDisposal) {
insertionDisposal();
insertionDisposal = null;
}
}, componentTagData.parentNodeList || true, false);
nodeList.expression = "<" + this.tag + ">";
teardownFunctions.push(function() {
Expand All @@ -681,8 +686,9 @@ var Component = Construct.extend(
if(componentInPage) {
viewModelDisconnectedCallback = viewModel.connectedCallback(el);
} else {
var insertionDisposal = domMutate.onNodeInsertion(el, function () {
insertionDisposal = domMutate.onNodeInsertion(el, function () {
insertionDisposal();
insertionDisposal = null;
viewModelDisconnectedCallback = viewModel.connectedCallback(el);
});
}
Expand Down

0 comments on commit 83ecafc

Please sign in to comment.