From ae24d2a7054f98176718cb97e58d7cae0c0a2c5e Mon Sep 17 00:00:00 2001 From: Ivan Hofer Date: Sun, 9 Jan 2022 11:00:23 +0100 Subject: [PATCH 1/4] fixes #7026 animations with multiple independent Svelte apps running at the same time --- src/runtime/internal/dom.ts | 2 +- src/runtime/internal/style_manager.ts | 29 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index a8b542053b47..f1c74aa5f67f 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -157,7 +157,7 @@ export function get_root_for_style(node: Node): ShadowRoot | Document { 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; + return style_element.sheet as CSSStyleSheet; } function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) { diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index 0993b3bf1833..3fcca2f95274 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,12 +1,12 @@ import { append_empty_stylesheet, get_root_for_style } from './dom'; import { raf } from './environment'; -interface ExtendedDoc extends Document { - __svelte_stylesheet: CSSStyleSheet; - __svelte_rules: Record; +interface StyleInformation { + stylesheet: CSSStyleSheet; + rules: Record; } -const active_docs = new Set(); +const active_docs = new Map(); let active = 0; // https://github.com/darkskyapp/string-hash/blob/master/index.js @@ -18,6 +18,12 @@ function hash(str: string) { return hash >>> 0; } +const create_style_information = (doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) => { + const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; + active_docs.set(doc, info); + return info; +}; + export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: number, duration: number, delay: number, ease: (t: number) => number, fn: (t: number, u: number) => string, uid: number = 0) { const step = 16.666 / duration; let keyframes = '{\n'; @@ -29,13 +35,12 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const name = `__svelte_${hash(rule)}_${uid}`; - const doc = get_root_for_style(node) as ExtendedDoc; - active_docs.add(doc); - const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_empty_stylesheet(node).sheet as CSSStyleSheet); - const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {}); + const doc = get_root_for_style(node); + + const { stylesheet, rules } = active_docs.get(doc) || create_style_information(doc, node); - if (!current_rules[name]) { - current_rules[name] = true; + if (!rules[name]) { + rules[name] = true; stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); } @@ -64,10 +69,10 @@ export function clear_rules() { raf(() => { if (active) return; active_docs.forEach(doc => { - const stylesheet = doc.__svelte_stylesheet; + const { stylesheet } = doc; let i = stylesheet.cssRules.length; while (i--) stylesheet.deleteRule(i); - doc.__svelte_rules = {}; + doc.rules = {}; }); active_docs.clear(); }); From 9b8445a0168c83aae8efd6ef2817ec9d5b8097f9 Mon Sep 17 00:00:00 2001 From: Ivan Hofer Date: Sun, 9 Jan 2022 11:58:06 +0100 Subject: [PATCH 2/4] use named function instead of inline function --- src/runtime/internal/style_manager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index 3fcca2f95274..00204c1ed493 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -18,11 +18,11 @@ function hash(str: string) { return hash >>> 0; } -const create_style_information = (doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) => { +function create_style_information(doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) { const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; active_docs.set(doc, info); return info; -}; +} export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: number, duration: number, delay: number, ease: (t: number) => number, fn: (t: number, u: number) => string, uid: number = 0) { const step = 16.666 / duration; From 276c177ab9d5900c534b29e5a5bd86fee7b1861e Mon Sep 17 00:00:00 2001 From: Ivan Hofer Date: Sun, 9 Jan 2022 11:59:27 +0100 Subject: [PATCH 3/4] rename `active_docs` to `managed_styles` --- src/runtime/internal/style_manager.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index 00204c1ed493..e44fccce28c9 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -6,7 +6,7 @@ interface StyleInformation { rules: Record; } -const active_docs = new Map(); +const managed_styles = new Map(); let active = 0; // https://github.com/darkskyapp/string-hash/blob/master/index.js @@ -20,7 +20,7 @@ function hash(str: string) { function create_style_information(doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) { const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; - active_docs.set(doc, info); + managed_styles.set(doc, info); return info; } @@ -37,7 +37,7 @@ 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 } = active_docs.get(doc) || create_style_information(doc, node); + const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node); if (!rules[name]) { rules[name] = true; @@ -68,12 +68,12 @@ export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string export function clear_rules() { raf(() => { if (active) return; - active_docs.forEach(doc => { - const { stylesheet } = doc; + managed_styles.forEach(info => { + const { stylesheet } = info; let i = stylesheet.cssRules.length; while (i--) stylesheet.deleteRule(i); - doc.rules = {}; + info.rules = {}; }); - active_docs.clear(); + managed_styles.clear(); }); } From 19cb2ebfb47f6e44db012747f0fa6622a5df66c6 Mon Sep 17 00:00:00 2001 From: Ivan Hofer Date: Sun, 9 Jan 2022 12:06:18 +0100 Subject: [PATCH 4/4] document why there could be multiple documents --- src/runtime/internal/style_manager.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index e44fccce28c9..6907e5af0294 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -6,6 +6,8 @@ interface StyleInformation { rules: Record; } +// we need to store the information for multiple documents because a Svelte application could also contain iframes +// https://github.com/sveltejs/svelte/issues/3624 const managed_styles = new Map(); let active = 0;