simpler createRawSnippet API

pull/12425/head
Rich Harris 2 years ago
parent 40d119158c
commit 1e4c6a2cbf

@ -60,10 +60,6 @@
> The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
## snippet_missing_mount
> Snippets created with `createRawSnippet(...)` and used on the client must specify a `mount` function
## state_prototype_fixed
> Cannot set prototype of `$state` object

@ -1,7 +1,3 @@
## lifecycle_function_unavailable
> `%name%(...)` is not available on the server
## snippet_missing_render
> Snippets created with `createRawSnippet(...)` and used on the server must specify a `render` function

@ -1,5 +1,6 @@
/** @import { Effect, TemplateNode } from '#client' */
/** @import { Getters } from '#shared' */
import { run } from '../../../shared/utils.js';
import { add_snippet_symbol } from '../../../shared/validate.js';
import { EFFECT_TRANSPARENT } from '../../constants.js';
import { branch, block, destroy_effect } from '../../reactivity/effects.js';
@ -8,8 +9,8 @@ import {
set_dev_current_component_function
} from '../../runtime.js';
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
import { create_fragment_from_html } from '../reconciler.js';
import { assign_nodes } from '../template.js';
import * as e from '../../errors.js';
/**
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
@ -65,20 +66,15 @@ export function wrap_snippet(component, fn) {
}
/**
* Create a snippet imperatively using mount, hydrate and render functions.
* Create a snippet programmatically
* @template {unknown[]} Params
* @param {{
* mount?: (...params: Getters<Params>) => Element,
* hydrate?: (element: Element, ...params: Getters<Params>) => void,
* render?: (...params: Params) => string
* render: (...params: Params) => string
* update?: (element: Element, ...params: Getters<Params>) => void,
* }} options
* @returns {import('svelte').Snippet<Params>}
*/
export function createRawSnippet({ mount, hydrate }) {
if (mount === undefined) {
e.snippet_missing_mount();
}
export function createRawSnippet({ render, update }) {
return add_snippet_symbol(
(/** @type {TemplateNode} */ anchor, /** @type {Getters<Params>} */ ...params) => {
/** @type {Element} */
@ -87,17 +83,14 @@ export function createRawSnippet({ mount, hydrate }) {
if (hydrating) {
element = /** @type {Element} */ (hydrate_node);
hydrate_next();
if (hydrate === undefined) {
element.replaceWith((element = mount(...params)));
} else {
hydrate(element, ...params);
}
} else {
element = mount(...params);
var html = render(.../** @type {Params} */ (params.map(run)));
var fragment = create_fragment_from_html(html);
element = /** @type {Element} */ (fragment.firstChild);
anchor.before(element);
}
update?.(element, ...params);
assign_nodes(element, element);
}
);

@ -262,22 +262,6 @@ export function rune_outside_svelte(rune) {
}
}
/**
* Snippets created with `createRawSnippet(...)` and used on the client must specify a `mount` function
* @returns {never}
*/
export function snippet_missing_mount() {
if (DEV) {
const error = new Error(`snippet_missing_mount\nSnippets created with \`createRawSnippet(...)\` and used on the client must specify a \`mount\` function`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("snippet_missing_mount");
}
}
/**
* Cannot set prototype of `$state` object
* @returns {never}

@ -1,23 +1,21 @@
/** @import { Snippet } from 'svelte' */
/** @import { Payload } from '#server' */
/** @import { Getters } from '#shared' */
import { add_snippet_symbol } from '../../shared/validate.js';
import * as e from '../errors.js';
/**
* Create a snippet imperatively using mount, hyrdate and render functions.
* Create a snippet programmatically
* @template {unknown[]} Params
* @param {{
* mount?: (...params: any[]) => Element,
* hydrate?: (element: Element, ...params: any[]) => void,
* render?: (...params: any[]) => string
* render: (...params: Params) => string
* update?: (element: Element, ...params: Getters<Params>) => void,
* }} options
* @returns {Snippet<Params>}
*/
export function createRawSnippet({ render }) {
if (render === undefined) {
e.snippet_missing_render();
}
const snippet_fn = (/** @type {Payload} */ payload, /** @type {any[]} */ ...args) => {
const snippet_fn = (/** @type {Payload} */ payload, /** @type {Params} */ ...args) => {
payload.out += render(...args);
};
add_snippet_symbol(snippet_fn);
return snippet_fn;
return /** @type {Snippet} */ (snippet_fn);
}

@ -8,17 +8,6 @@
export function lifecycle_function_unavailable(name) {
const error = new Error(`lifecycle_function_unavailable\n\`${name}(...)\` is not available on the server`);
error.name = 'Svelte error';
throw error;
}
/**
* Snippets created with `createRawSnippet(...)` and used on the server must specify a `render` function
* @returns {never}
*/
export function snippet_missing_render() {
const error = new Error(`snippet_missing_render\nSnippets created with \`createRawSnippet(...)\` and used on the server must specify a \`render\` function`);
error.name = 'Svelte error';
throw error;
}

@ -2,16 +2,11 @@
import { createRawSnippet } from 'svelte';
const snippet = createRawSnippet({
mount() {
const p = document.createElement('p');
p.textContent = 'mounted';
return p;
},
hydrate(p) {
p.textContent = 'hydrated';
},
render() {
return `<p>rendered</p>`;
},
update(p) {
p.textContent = 'hydrated';
}
});
</script>

@ -1,3 +0,0 @@
import { test } from '../../test';
export default test({});

@ -1,16 +0,0 @@
<script>
import { createRawSnippet } from 'svelte';
const snippet = createRawSnippet({
mount() {
const p = document.createElement('p');
p.textContent = 'mounted';
return p;
},
render() {
return `<p>rendered</p>`;
}
});
</script>
{@render snippet()}

@ -1,17 +0,0 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true // Render in dev mode to check that the validation error is not thrown
},
html: `<div><div>0</div></div><button>+</button>`,
test({ assert, target }) {
const [b1] = target.querySelectorAll('button');
b1?.click();
flushSync();
assert.htmlEqual(target.innerHTML, `<div><div>1</div></div><button>+</button>`);
}
});

@ -1,32 +0,0 @@
<script>
import { createRawSnippet } from 'svelte';
let count = $state(0);
const snippet = createRawSnippet({
mount(count) {
const div = document.createElement('div');
$effect(() => {
div.textContent = count();
});
return div;
},
hydrate(element, count) {
$effect(() => {
element.textContent = count();
});
},
render(count) {
return `<div>${count}</div>`;
}
});
</script>
<div>
{@render snippet(count)}
</div>
<button onclick={() => count++}>+</button>

@ -4,17 +4,13 @@
let count = $state(0);
const hello = createRawSnippet({
mount(count) {
const p = document.createElement('p')
render(count) {
return `<p>clicks: ${count}</p>`;
},
update(p, count) {
$effect(() => {
p.textContent = `clicks: ${count()}`
});
return p;
},
render(count) {
return `<p>clicks: ${count}</p>`;
}
});
</script>

Loading…
Cancel
Save