Skip to content

Commit afd3849

Browse files
fix: provide a workaround for unsafe-inline CSP that also works in Safari (#7800)
This changes the inserted style element for transitions to initially include the string '/* empty */'. This allows you to work around requiring unsafe-inline CSP discussed in #6662 by adding a hash to your CSP: 'sha256-9OlNO0DNEeaVzHL4RZwCLsBHA8WBQ8toBp/4F5XV2nc=' --------- Co-authored-by: Simon H <[email protected]>
1 parent c036396 commit afd3849

File tree

8 files changed

+40
-38
lines changed

8 files changed

+40
-38
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* Add `a11y-no-static-element-interactions`rule ([#8251](https://github.com/sveltejs/svelte/pull/8251))
1717
* Bind `null` option and input values consistently ([#8312](https://github.com/sveltejs/svelte/issues/8312))
1818
* Allow `$store` to be used with changing values including nullish values ([#7555](https://github.com/sveltejs/svelte/issues/7555))
19+
* Initialize stylesheet with `/* empty */` to enable setting CSP directive that also works in Safari ([#7800](https://github.com/sveltejs/svelte/pull/7800))
20+
* Treat slots as if they don't exist when using CSS adjacent and general sibling combinators ([#8284](https://github.com/sveltejs/svelte/issues/8284))
1921

2022
## Unreleased (3.0)
2123

src/compiler/compile/css/Selector.ts

+15-21
Original file line numberDiff line numberDiff line change
@@ -471,28 +471,22 @@ function get_element_parent(node: Element): Element | null {
471471
}
472472

473473
/**
474-
* Finds the given node's previous sibling in the DOM
475-
*
476-
* Unless the component is a custom element (web component), which in this
477-
* case, the <slot> element is actually real, the Svelte <slot> is just a
478-
* placeholder and is not actually real. Any children nodes in <slot>
479-
* are 'flattened' and considered as the same level as the <slot>'s siblings
480-
*
481-
* e.g.
482-
* <h1>Heading 1</h1>
483-
* <slot>
484-
* <h2>Heading 2</h2>
485-
* </slot>
486-
*
487-
* is considered to look like:
488-
* <h1>Heading 1</h1>
489-
* <h2>Heading 2</h2>
490-
*/
474+
* Finds the given node's previous sibling in the DOM
475+
*
476+
* The Svelte <slot> is just a placeholder and is not actually real. Any children nodes
477+
* in <slot> are 'flattened' and considered as the same level as the <slot>'s siblings
478+
*
479+
* e.g.
480+
* <h1>Heading 1</h1>
481+
* <slot>
482+
* <h2>Heading 2</h2>
483+
* </slot>
484+
*
485+
* is considered to look like:
486+
* <h1>Heading 1</h1>
487+
* <h2>Heading 2</h2>
488+
*/
491489
function find_previous_sibling(node: INode): INode {
492-
if (node.component.compile_options.customElement) {
493-
return node.prev;
494-
}
495-
496490
let current_node: INode = node;
497491
do {
498492
if (current_node.type === 'Slot') {

src/runtime/internal/dom.ts

+6
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ export function get_root_for_style(node: Node): ShadowRoot | Document {
157157

158158
export function append_empty_stylesheet(node: Node) {
159159
const style_element = element('style') as HTMLStyleElement;
160+
// For transitions to work without 'style-src: unsafe-inline' Content Security Policy,
161+
// these empty tags need to be allowed with a hash as a workaround until we move to the Web Animations API.
162+
// Using the hash for the empty string (for an empty tag) works in all browsers except Safari.
163+
// So as a workaround for the workaround, when we append empty style tags we set their content to /* empty */.
164+
// The hash 'sha256-9OlNO0DNEeaVzHL4RZwCLsBHA8WBQ8toBp/4F5XV2nc=' will then work even in Safari.
165+
style_element.textContent = '/* empty */';
160166
append_stylesheet(get_root_for_style(node), style_element);
161167
return style_element.sheet as CSSStyleSheet;
162168
}

test/runtime-puppeteer/samples/style_manager-cleanup/_config.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ export default {
55
test: async ({ component, assert, window, waitUntil }) => {
66
assert.htmlEqual(window.document.head.innerHTML, '');
77
component.visible = true;
8-
assert.htmlEqual(window.document.head.innerHTML, '<style></style>');
8+
assert.htmlEqual(window.document.head.innerHTML, '<style>/* empty */</style>');
99
await waitUntil(() => window.document.head.innerHTML === '');
1010
assert.htmlEqual(window.document.head.innerHTML, '');
1111

1212
component.visible = false;
13-
assert.htmlEqual(window.document.head.innerHTML, '<style></style>');
13+
assert.htmlEqual(window.document.head.innerHTML, '<style>/* empty */</style>');
1414
await waitUntil(() => window.document.head.innerHTML === '');
1515
assert.htmlEqual(window.document.head.innerHTML, '');
1616
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<svelte:options tag="my-element" />
1+
<svelte:options customElement="my-element" />
22

33
<h1>Heading 1</h1>
44
<span>Span 1</span>
@@ -8,13 +8,13 @@
88
</slot>
99

1010
<style>
11-
/* This will not get picked up */
12-
h1 ~ p {
11+
/* This will not be picked up */
12+
h1 ~ slot > p {
1313
color: red;
1414
}
1515
16-
/* This will be picked up */
17-
h1 ~ slot > p {
16+
/* This will get picked up */
17+
h1 ~ p {
1818
color: red;
1919
}
2020
</style>

test/validator/samples/general-siblings-combinator-in-custom-element-selects-slot-fallback/warnings.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[
22
{
33
"code": "css-unused-selector",
4-
"message": "Unused CSS selector \"h1 ~ p\"",
4+
"message": "Unused CSS selector \"h1 ~ slot > p\"",
55
"start": {
66
"column": 1,
77
"line": 12
88
},
99
"end": {
10-
"column": 7,
10+
"column": 14,
1111
"line": 12
1212
}
1313
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<svelte:options tag="custom-element" />
1+
<svelte:options customElement="custom-element" />
22

33
<h1>test</h1>
44
<slot>
@@ -7,12 +7,12 @@
77

88
<style>
99
/* This will not be picked up */
10-
h1 + span {
11-
color: red;
12-
}
10+
h1 + slot > span {
11+
color: red;
12+
}
1313
1414
/* This will be picked up */
15-
h1 + slot > span {
15+
h1 + span {
1616
color: red;
1717
}
1818
</style>

test/validator/samples/siblings-combinator-in-custom-element-selects-slot-fallback/warnings.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
{
33
"code": "css-unused-selector",
44
"end": {
5-
"column": 11,
5+
"column": 17,
66
"line": 10
77
},
8-
"message": "Unused CSS selector \"h1 + span\"",
8+
"message": "Unused CSS selector \"h1 + slot > span\"",
99
"start": {
10-
"column": 2,
10+
"column": 1,
1111
"line": 10
1212
}
1313
}

0 commit comments

Comments
 (0)