Skip to content

Commit 587c1b1

Browse files
committed
fix: correctly validate head snippets on the server
1 parent 3153384 commit 587c1b1

File tree

5 files changed

+57
-15
lines changed

5 files changed

+57
-15
lines changed

.changeset/dirty-zebras-do.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: correctly validate head snippets on the server

packages/svelte/src/internal/server/dev.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from '../../html-tree-validation.js';
77
import { current_component } from './context.js';
88
import { invalid_snippet_arguments } from '../shared/errors.js';
9-
import { Payload } from './payload.js';
9+
import { HeadPayload, Payload } from './payload.js';
1010

1111
/**
1212
* @typedef {{
@@ -105,7 +105,11 @@ export function pop_element() {
105105
* @param {Payload} payload
106106
*/
107107
export function validate_snippet_args(payload) {
108-
if (typeof payload !== 'object' || !(payload instanceof Payload)) {
108+
if (
109+
typeof payload !== 'object' ||
110+
// for some reason typescript consider the type of payload as never after the first instanceof
111+
!(payload instanceof Payload || /** @type {any} */ (payload) instanceof HeadPayload)
112+
) {
109113
invalid_snippet_arguments();
110114
}
111115
}

packages/svelte/src/internal/server/payload.js

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
1+
export class HeadPayload {
2+
/** @type {Set<{ hash: string; code: string }>} */
3+
css = new Set();
4+
out = '';
5+
uid = () => '';
6+
title = '';
7+
8+
constructor(css = new Set(), out = '', title = '', uid = () => '') {
9+
this.css = css;
10+
this.out = out;
11+
this.title = title;
12+
this.uid = uid;
13+
}
14+
15+
clone() {
16+
const payload = new HeadPayload();
17+
18+
payload.out = this.out;
19+
payload.css = new Set(this.css);
20+
payload.title = this.title;
21+
payload.uid = this.uid;
22+
23+
return payload;
24+
}
25+
}
26+
127
export class Payload {
228
/** @type {Set<{ hash: string; code: string }>} */
329
css = new Set();
430
out = '';
531
uid = () => '';
632

7-
head = {
8-
/** @type {Set<{ hash: string; code: string }>} */
9-
css: new Set(),
10-
title: '',
11-
out: '',
12-
uid: () => ''
13-
};
33+
head = new HeadPayload();
1434

1535
constructor(id_prefix = '') {
1636
this.uid = props_id_generator(id_prefix);
@@ -30,12 +50,7 @@ export function copy_payload({ out, css, head, uid }) {
3050
payload.css = new Set(css);
3151
payload.uid = uid;
3252

33-
payload.head = {
34-
title: head.title,
35-
out: head.out,
36-
css: new Set(head.css),
37-
uid: head.uid
38-
};
53+
payload.head = head.clone();
3954

4055
return payload;
4156
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
compileOptions: {
5+
dev: true
6+
},
7+
mode: ['server'],
8+
async test({ errors, assert }) {
9+
assert.equal(errors, []);
10+
}
11+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{#snippet head()}
2+
<title>Cool</title>
3+
{/snippet}
4+
5+
<svelte:head>
6+
{@render head()}
7+
</svelte:head>

0 commit comments

Comments
 (0)