Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-bind placeholder nodes after they reconnect to the document #156

Merged
merged 5 commits into from
Jan 6, 2020

Conversation

bmomberger-bitovi
Copy link
Contributor

Sometimes users will move component markup around in the DOM. A reduced example can be seen here: https://codepen.io/bmomberger-bitovi/pen/bGNYvBg?editors=1010

The underlying reason for this is that can-view-live tears down live binding on placeholders when those placeholders are removed from the document. But this also breaks live binding on nodes which are just getting shuffled around by other code. This can happen with jQuery plugins and other mutating libraries that happen to work alongside CanJS.

This PR addresses this possibility by letting removed placeholder nodes re-bind if they are later added to the document.

@bmomberger-bitovi bmomberger-bitovi requested review from phillipskevin and justinbmeyer and removed request for phillipskevin January 4, 2020 00:53
@bmomberger-bitovi
Copy link
Contributor Author

bmomberger-bitovi commented Jan 4, 2020

The additional text test is currently failing on IE11. After removing the text node, no updates happen even after reconnection. This will have to be considered a WIP until that failure is addressed, but should still be reviewed.

@bmomberger-bitovi bmomberger-bitovi changed the title Re-bind placeholder nodes after they reconnect to the document [WIP] Re-bind placeholder nodes after they reconnect to the document Jan 4, 2020
@@ -65,10 +64,6 @@ module.exports = function(el, compute, viewInsertSymbolOptions) {
}
//!steal-remove-end

var doNotUpdateRange = function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of the patch set is boyscouting from the queue changes I made recently. Since updateRange is never queued, it is not necessary to remove it from the dom queue.

@justinbmeyer
Copy link
Contributor

Does the ability to rebind create a memory leak? I couldn’t think of a way to make this work without creating a memory leak.

Does can-view-live support move anymore? I might have made a way to ignore DOM nodes moving.

@bmomberger-bitovi
Copy link
Contributor Author

I don't think this is in danger of memory leaks now that we only use WeakMaps in can-dom-mutate. I tried profiling the window from the QUnit tests to see for sure, and what I found was that the only "leaks" came from the no can.setElement symbol on observable warnings and one test that set up a mutation listener on the document body.

@justinbmeyer
Copy link
Contributor

I thought can-dom-mutate also held things in normal arrays and such so it could loop through handlers

@bmomberger-bitovi
Copy link
Contributor Author

bmomberger-bitovi commented Jan 5, 2020

I think you're referring to https://github.com/canjs/can-dom-mutate/blob/master/can-dom-mutate.js#L84-L87 ?

The arrays are keyed on the elements (and documents) in the WeakMaps, so when elements are garbage collected the whole array is also GC'ed.

Mutation records are held in normal arrays while flushing and queueing, but those arrays are emptied regularly.

@bmomberger-bitovi
Copy link
Contributor Author

If you're still concerned about leaks, I adapted the benchmark test from can-dom-mutate, and can show that after you create, insert, and remove a bunch of elements (both text and comment placeholders), once garbage is collected, the weakmap is empty of entries:

can-view-live-no-leak

@bmomberger-bitovi bmomberger-bitovi changed the title [WIP] Re-bind placeholder nodes after they reconnect to the document Re-bind placeholder nodes after they reconnect to the document Jan 6, 2020
@bmomberger-bitovi
Copy link
Contributor Author

For reference this is the function being run on click:

	function run() {
		var doc = document.implementation.createHTMLDocument();
		var div = doc.createElement("div");
		doc.body.appendChild(div);
		// create range of comments
		div.appendChild(doc.createComment(""));
		div.appendChild(doc.createComment("can-end-placeholder"));
		live.html(div.firstChild, new Observation(() => "<span>foo</span>"));
		var text = doc.createTextNode("bar");
		div.appendChild(text);
		live.text(text, new Observation(() => "baz"));

		DOCUMENT(doc);
		doc.body.removeChild(div);
		DOCUMENT(document);
	}

@bmomberger-bitovi bmomberger-bitovi merged commit 6819e3a into master Jan 6, 2020
@bmomberger-bitovi bmomberger-bitovi deleted the bind-reconnected-nodes branch January 6, 2020 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants