Skip to content

Commit 806cba2

Browse files
authored
[fix] ensure style manager instances don't conflict with each other (#7114)
1 parent 1143b56 commit 806cba2

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

src/runtime/internal/dom.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export function get_root_for_style(node: Node): ShadowRoot | Document {
157157
export function append_empty_stylesheet(node: Node) {
158158
const style_element = element('style') as HTMLStyleElement;
159159
append_stylesheet(get_root_for_style(node), style_element);
160-
return style_element;
160+
return style_element.sheet as CSSStyleSheet;
161161
}
162162

163163
function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) {

src/runtime/internal/style_manager.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { append_empty_stylesheet, get_root_for_style } from './dom';
22
import { raf } from './environment';
33

4-
interface ExtendedDoc extends Document {
5-
__svelte_stylesheet: CSSStyleSheet;
6-
__svelte_rules: Record<string, true>;
4+
interface StyleInformation {
5+
stylesheet: CSSStyleSheet;
6+
rules: Record<string, true>;
77
}
88

9-
const active_docs = new Set<ExtendedDoc>();
9+
// we need to store the information for multiple documents because a Svelte application could also contain iframes
10+
// https://github.com/sveltejs/svelte/issues/3624
11+
const managed_styles = new Map<Document | ShadowRoot, StyleInformation>();
1012
let active = 0;
1113

1214
// https://github.com/darkskyapp/string-hash/blob/master/index.js
@@ -18,6 +20,12 @@ function hash(str: string) {
1820
return hash >>> 0;
1921
}
2022

23+
function create_style_information(doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) {
24+
const info = { stylesheet: append_empty_stylesheet(node), rules: {} };
25+
managed_styles.set(doc, info);
26+
return info;
27+
}
28+
2129
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) {
2230
const step = 16.666 / duration;
2331
let keyframes = '{\n';
@@ -29,13 +37,12 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
2937

3038
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
3139
const name = `__svelte_${hash(rule)}_${uid}`;
32-
const doc = get_root_for_style(node) as ExtendedDoc;
33-
active_docs.add(doc);
34-
const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_empty_stylesheet(node).sheet as CSSStyleSheet);
35-
const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});
40+
const doc = get_root_for_style(node);
41+
42+
const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);
3643

37-
if (!current_rules[name]) {
38-
current_rules[name] = true;
44+
if (!rules[name]) {
45+
rules[name] = true;
3946
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
4047
}
4148

@@ -63,12 +70,12 @@ export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string
6370
export function clear_rules() {
6471
raf(() => {
6572
if (active) return;
66-
active_docs.forEach(doc => {
67-
const stylesheet = doc.__svelte_stylesheet;
73+
managed_styles.forEach(info => {
74+
const { stylesheet } = info;
6875
let i = stylesheet.cssRules.length;
6976
while (i--) stylesheet.deleteRule(i);
70-
doc.__svelte_rules = {};
77+
info.rules = {};
7178
});
72-
active_docs.clear();
79+
managed_styles.clear();
7380
});
7481
}

0 commit comments

Comments
 (0)