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..6907e5af0294 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,12 +1,14 @@ 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(); +// 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; // https://github.com/darkskyapp/string-hash/blob/master/index.js @@ -18,6 +20,12 @@ 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: {} }; + managed_styles.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 +37,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 } = managed_styles.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); } @@ -63,12 +70,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.__svelte_stylesheet; + managed_styles.forEach(info => { + const { stylesheet } = info; let i = stylesheet.cssRules.length; while (i--) stylesheet.deleteRule(i); - doc.__svelte_rules = {}; + info.rules = {}; }); - active_docs.clear(); + managed_styles.clear(); }); }