[fix] no root node for detached dom node (#6570)

pull/6577/head
Tan Li Hau 3 years ago committed by GitHub
parent a3fb765d6f
commit 1952ea22de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -134,9 +134,9 @@ export function append_styles(
style_sheet_id: string, style_sheet_id: string,
styles: string styles: string
) { ) {
const append_styles_to = get_root_for_styles(target); const append_styles_to = get_root_for_style(target);
if (!append_styles_to?.getElementById(style_sheet_id)) { if (!append_styles_to.getElementById(style_sheet_id)) {
const style = element('style'); const style = element('style');
style.id = style_sheet_id; style.id = style_sheet_id;
style.textContent = styles; style.textContent = styles;
@ -144,20 +144,19 @@ export function append_styles(
} }
} }
export function get_root_for_node(node: Node) { export function get_root_for_style(node: Node): ShadowRoot | Document {
if (!node) return document; if (!node) return document;
return (node.getRootNode ? node.getRootNode() : node.ownerDocument); // check for getRootNode because IE is still supported const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
} if ((root as ShadowRoot).host) {
return root as ShadowRoot;
function get_root_for_styles(node: Node) { }
const root = get_root_for_node(node); return document;
return (root as ShadowRoot).host ? root as ShadowRoot : root as Document;
} }
export function append_empty_stylesheet(node: Node) { export function append_empty_stylesheet(node: Node) {
const style_element = element('style') as HTMLStyleElement; const style_element = element('style') as HTMLStyleElement;
append_stylesheet(get_root_for_styles(node), style_element); append_stylesheet(get_root_for_style(node), style_element);
return style_element; return style_element;
} }

@ -1,4 +1,4 @@
import { append_empty_stylesheet, get_root_for_node } from './dom'; import { append_empty_stylesheet, get_root_for_style } from './dom';
import { raf } from './environment'; import { raf } from './environment';
interface ExtendedDoc extends Document { interface ExtendedDoc extends Document {
@ -29,7 +29,7 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b:
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
const name = `__svelte_${hash(rule)}_${uid}`; const name = `__svelte_${hash(rule)}_${uid}`;
const doc = get_root_for_node(node) as unknown as ExtendedDoc; const doc = get_root_for_style(node) as ExtendedDoc;
active_docs.add(doc); active_docs.add(doc);
const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_empty_stylesheet(node).sheet as CSSStyleSheet); 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 current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});

@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>
<div>Hello {name}</div>
<style>
div {
color: red;
}
</style>

@ -0,0 +1,16 @@
export default {
skip_if_ssr: true,
compileOptions: {
cssHash: () => 'svelte-xyz'
},
async test({ assert, component, target, window }) {
assert.htmlEqual(
window.document.head.innerHTML,
'<style id="svelte-xyz">div.svelte-xyz{color:red}</style>'
);
assert.htmlEqual(
component.div.innerHTML,
'<div class="svelte-xyz">Hello World</div>'
);
}
};

@ -0,0 +1,18 @@
<script>
import App from './App.svelte';
import { onMount } from 'svelte';
export let div;
onMount(() => {
div = document.createElement('div');
const app = new App({
target: div
});
return () => {
app.$destroy();
}
});
</script>

@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>
<div>Hello {name}</div>
<style>
div {
color: red;
}
</style>

@ -0,0 +1,16 @@
export default {
skip_if_ssr: true,
compileOptions: {
cssHash: () => 'svelte-xyz'
},
async test({ assert, component, target, window }) {
assert.htmlEqual(
window.document.head.innerHTML,
'<style id="svelte-xyz">div.svelte-xyz{color:red}</style>'
);
assert.htmlEqual(
component.div.innerHTML,
'<div class="svelte-xyz">Hello World</div>'
);
}
};

@ -0,0 +1,18 @@
<script>
import App from './App.svelte';
import { onMount } from 'svelte';
export let div;
onMount(() => {
const app = new App({
target: div
});
return () => {
app.$destroy();
}
});
</script>
<div bind:this={div} />

@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>
<div>Hello {name}</div>
<style>
div {
color: red;
}
</style>

@ -0,0 +1,13 @@
export default {
skip_if_ssr: true,
compileOptions: {
cssHash: () => 'svelte-xyz'
},
async test({ assert, component, target, window }) {
assert.htmlEqual(window.document.head.innerHTML, '');
assert.htmlEqual(component.div.shadowRoot.innerHTML, `
<style id="svelte-xyz">div.svelte-xyz{color:red}</style>
<div class="svelte-xyz">Hello World</div>
`);
}
};

@ -0,0 +1,19 @@
<script>
import App from './App.svelte';
import { onMount } from 'svelte';
export let div;
onMount(() => {
const root = div.attachShadow({ mode: 'open' });
const app = new App({
target: root
});
return () => {
app.$destroy();
}
});
</script>
<div bind:this={div} />
Loading…
Cancel
Save