Skip to content

Commit

Permalink
fixed removal of empty stylesheets created from transitions (#7662)
Browse files Browse the repository at this point in the history
Co-authored-by: Mathias Picker <mattis123@live.no>
  • Loading branch information
tanhauhau and MathiasWP committed Jul 17, 2022
1 parent 05b5be0 commit 26d1455
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
9 changes: 2 additions & 7 deletions src/runtime/internal/dom.ts
Expand Up @@ -154,14 +154,9 @@ export function get_root_for_style(node: Node): ShadowRoot | Document {
return node.ownerDocument;
}

export function append_empty_stylesheet(node: Node) {
const style_element = element('style') as HTMLStyleElement;
append_stylesheet(get_root_for_style(node), style_element);
return style_element.sheet as CSSStyleSheet;
}

function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) {
export function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) {
append((node as Document).head || node, style);
return style.sheet as CSSStyleSheet;
}

export function append_hydration(target: NodeEx, node: NodeEx) {
Expand Down
17 changes: 8 additions & 9 deletions src/runtime/internal/style_manager.ts
@@ -1,8 +1,8 @@
import { append_empty_stylesheet, get_root_for_style } from './dom';
import { append_stylesheet, detach, element, get_root_for_style } from './dom';
import { raf } from './environment';

interface StyleInformation {
stylesheet: CSSStyleSheet;
style_element: HTMLStyleElement;
rules: Record<string, true>;
}

Expand All @@ -20,8 +20,8 @@ function hash(str: string) {
return hash >>> 0;
}

function create_style_information(doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) {
const info = { stylesheet: append_empty_stylesheet(node), rules: {} };
function create_style_information(doc: Document | ShadowRoot) {
const info = { style_element: element('style'), rules: {} };
managed_styles.set(doc, info);
return info;
}
Expand All @@ -39,9 +39,10 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
const name = `__svelte_${hash(rule)}_${uid}`;
const doc = get_root_for_style(node);

const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);
const { style_element, rules } = managed_styles.get(doc) || create_style_information(doc);

if (!rules[name]) {
const stylesheet = append_stylesheet(doc, style_element);
rules[name] = true;
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
}
Expand Down Expand Up @@ -71,10 +72,8 @@ export function clear_rules() {
raf(() => {
if (active) return;
managed_styles.forEach(info => {
const { stylesheet } = info;
let i = stylesheet.cssRules.length;
while (i--) stylesheet.deleteRule(i);
info.rules = {};
const { style_element } = info;
detach(style_element);
});
managed_styles.clear();
});
Expand Down
14 changes: 14 additions & 0 deletions test/runtime/samples/style_manager-cleanup/_config.js
@@ -0,0 +1,14 @@
export default {
skip_if_ssr: true,
skip_if_hydrate: true,
skip_if_hydrate_from_ssr: true,
test({ raf, assert, component, window }) {
component.visible = true;
raf.tick(100);
component.visible = false;
raf.tick(200);
raf.tick(0);

assert.htmlEqual(window.document.head.innerHTML, '');
}
};
14 changes: 14 additions & 0 deletions test/runtime/samples/style_manager-cleanup/main.svelte
@@ -0,0 +1,14 @@
<script>
export let visible = false;
function foo() {
return {
duration: 100,
css: () => ''
};
}
</script>

{#if visible}
<div transition:foo></div>
{/if}

0 comments on commit 26d1455

Please sign in to comment.