Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions src/runtime/internal/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,30 +134,29 @@ export function append_styles(
style_sheet_id: 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');
style.id = style_sheet_id;
style.textContent = styles;
append_stylesheet(append_styles_to, style);
}
}

export function get_root_for_node(node: Node) {
export function get_root_for_style(node: Node): ShadowRoot | Document {
if (!node) return document;

return (node.getRootNode ? node.getRootNode() : node.ownerDocument); // check for getRootNode because IE is still supported
}

function get_root_for_styles(node: Node) {
const root = get_root_for_node(node);
return (root as ShadowRoot).host ? root as ShadowRoot : root as Document;
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
if ((root as ShadowRoot).host) {
return root as ShadowRoot;
}
return document;
Copy link
Contributor

@jacwright jacwright Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks transitions/animations in iframes (see #3625). Please return ownerDocument, not document.

return node.ownerDocument;

Once fixed, you can close #6637 😄

}

export function append_empty_stylesheet(node: Node) {
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;
}

Expand Down
4 changes: 2 additions & 2 deletions src/runtime/internal/style_manager.ts
Original file line number Diff line number Diff line change
@@ -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';

interface ExtendedDoc extends Document {
Expand Down Expand Up @@ -29,7 +29,7 @@ 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_node(node) as unknown as ExtendedDoc;
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 = {});
Expand Down
11 changes: 11 additions & 0 deletions test/runtime/samples/target-dom-detached/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>

<div>Hello {name}</div>

<style>
div {
color: red;
}
</style>
16 changes: 16 additions & 0 deletions test/runtime/samples/target-dom-detached/_config.js
Original file line number Diff line number Diff line change
@@ -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>'
);
}
};
18 changes: 18 additions & 0 deletions test/runtime/samples/target-dom-detached/main.svelte
Original file line number Diff line number Diff line change
@@ -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>
11 changes: 11 additions & 0 deletions test/runtime/samples/target-dom/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>

<div>Hello {name}</div>

<style>
div {
color: red;
}
</style>
16 changes: 16 additions & 0 deletions test/runtime/samples/target-dom/_config.js
Original file line number Diff line number Diff line change
@@ -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>'
);
}
};
18 changes: 18 additions & 0 deletions test/runtime/samples/target-dom/main.svelte
Original file line number Diff line number Diff line change
@@ -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} />
11 changes: 11 additions & 0 deletions test/runtime/samples/target-shadow-dom/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
let name = 'World';
</script>

<div>Hello {name}</div>

<style>
div {
color: red;
}
</style>
13 changes: 13 additions & 0 deletions test/runtime/samples/target-shadow-dom/_config.js
Original file line number Diff line number Diff line change
@@ -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>
`);
}
};
19 changes: 19 additions & 0 deletions test/runtime/samples/target-shadow-dom/main.svelte
Original file line number Diff line number Diff line change
@@ -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} />