Skip to content

Allow transitions and animations to work within iframes #3625

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

Merged
merged 8 commits into from
Mar 14, 2020
Merged

Conversation

jacwright
Copy link
Contributor

Svelte works great in iframes except for transitions and animations. This fixes that issue.

Fixes #3624.

Svelte works great in iframes except for transitions and animations. This fixes that issue.

See #3624.
Copy link
Member

@Rich-Harris Rich-Harris left a comment

Choose a reason for hiding this comment

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

Sorry for only getting to this now. Will admit I'd never considered this use case. Had a couple of small comments/questions

type DocStyles = [CSSStyleSheet, Record<string, true>];

let activeDocs = new Set<Document>();
let docStyles = new WeakMap<Document, DocStyles>();
Copy link
Member

Choose a reason for hiding this comment

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

We're not using WeakMap anywhere else currently, and I think we probably want that to continue being the case since it's basically impossible to polyfill in environments that don't support it. Reckon we could get away with this being a Map instead? In the vast majority of cases we're only going to have a single key, and it's always likely to be stable, so maybe it doesn't matter if we hang on to references?

doc.head.appendChild(style);
stylesheet = style.sheet as CSSStyleSheet;
docStyles.set(doc, [ stylesheet, current_rules ]);
}
Copy link
Member

Choose a reason for hiding this comment

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

This is obnoxious code-golfing, but if you wanted to save 18 bytes (after minification) you could do this...

const doc = node.ownerDocument;
activeDocs.add(doc);
const [stylesheet, current_rules] = (docStyles.has(doc) ? docStyles : docStyles.set(doc, [
	(doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet),
	{}
])).get(doc) as DocStyles;

Can we change docStyles to doc_styles?

@@ -53,14 +59,19 @@ export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string
)
.join(', ');

if (name && !--active) clear_rules();
active = Math.max(0, active - 1);
Copy link
Member

Choose a reason for hiding this comment

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

This feels like it's masking a bug — is the behaviour different when iframes are involved, or is this unrelated to iframes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it is masking a bug. Toggling a transition on and off multiple times has a memory leak.

Screen Shot 2019-11-19 at 4 37 43 PM

while (i--) stylesheet.deleteRule(i);
docStyles.set(doc, [ stylesheet, {} ]);
});
activeDocs.clear();
Copy link
Member

Choose a reason for hiding this comment

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

oh! we can definitely use a Map instead of a WeakMap if we're clearing activeDocs (can we change it to active_docs?)

@@ -53,14 +55,19 @@ export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string
)
.join(', ');

if (name && !--active) clear_rules();
active = Math.max(0, active - 1);
if (name && !active) clear_rules();
Copy link

Choose a reason for hiding this comment

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

I've been working off of this branch (since my Svelte app needs iframe support) and noticed that this change causes a previously working transition of mine to get cut short mid-transition.

It's more noticeable with a longer transition duration. For example, with duration=5s, the first 2s or so of the transition work as expected, but then it jumps to the final position suddenly. This is the case both in and outside of an iframe.

My use case is pretty simple, just: <div transition:slide={...}>. Reverting just the above 3 lines fixes the issue for me, although then the leak is still present of course.

I will add a ticket to document the leak.
`doc_styles` was a leak as it was keeping old iframe docs in memory. By adding the stylesheet info on the document object it can be cleaned up (poor man's weakmap).

`delete_rule` can potentially be called many times and if called without the `name` value it may remove all the rules but not track it correctly. The logic is updated to clear rules when there are no active transitions left.
@jacwright
Copy link
Contributor Author

I've updated the PR to latest Svelte, fixed memory leaks by solidifying the logic in delete_rules while still allowing it to be called multiple times and getting rid of the Map which really needed to be a WeakMap. Storing the necessary data on the document object is a poor man's WeakMap.

@jtormey I would love it you could test this in your situation. If it cuts transitions short, it is because of a bug in internal/transitions.ts where it may be calling delete_rules too aggressively. I did not feel comfortable enough with that code to understand if/where it might be (i.e. I did not want to spend the time fixing any possible bugs in there for this PR). The logic in style_manager is correct now and deletes the rules when no elements have their __svelte* animations on them anymore.

Ready for another review @Rich-Harris. :D

@jtormey
Copy link

jtormey commented Mar 2, 2020

Just retested with your latest changes, the transition no longer gets cut short! 🎉

@Conduitry Conduitry merged commit 966aae3 into master Mar 14, 2020
@Conduitry Conduitry deleted the gh-3624 branch March 14, 2020 20:37
@jacwright
Copy link
Contributor Author

Thanks @Conduitry! 🎉

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.

Allow transitions to work within iFrames
4 participants