pull/13083/head
Dominic Gannaway 2 years ago
parent 8ace4d02cb
commit a241a5a5b6

@ -48,6 +48,10 @@
> Failed to hydrate the application
## invalid_snippet
> Could not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`
## lifecycle_legacy_only
> `%name%(...)` cannot be used in runes mode

@ -32,7 +32,7 @@ export function RenderTag(node, context) {
if (node.metadata.dynamic) {
// If we have a chain expression then ensure a nullish snippet function gets turned into an empty one
if (node.expression.type === 'ChainExpression') {
snippet_function = b.logical('??', snippet_function, b.id('$.empty_snippet'));
snippet_function = b.logical('??', snippet_function, b.id('$.noop'));
}
context.state.init.push(

@ -11,8 +11,10 @@ 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 w from '../../warnings.js';
import * as e from '../../errors.js';
import { DEV } from 'esm-env';
import { get_first_child, get_next_sibling } from '../operations.js';
import { noop } from '../../../shared/utils.js';
/**
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
@ -25,7 +27,8 @@ export function snippet(node, get_snippet, ...args) {
var anchor = node;
/** @type {SnippetFn | null | undefined} */
var snippet = /** @type {SnippetFn} */ (empty_snippet);
// @ts-ignore
var snippet = noop;
/** @type {Effect | null} */
var snippet_effect;
@ -38,6 +41,10 @@ export function snippet(node, get_snippet, ...args) {
snippet_effect = null;
}
if (DEV && snippet == null) {
e.invalid_snippet();
}
snippet_effect = branch(() => /** @type {SnippetFn} */ (snippet)(anchor, ...args));
}, EFFECT_TRANSPARENT);
@ -46,10 +53,6 @@ export function snippet(node, get_snippet, ...args) {
}
}
// Just an empty function
/** @type {(...args: any[]) => void} */
export const empty_snippet = () => {};
/**
* In development, wrap the snippet function so that it passes validation, and so that the
* correct component context is set for ownership checks

@ -210,6 +210,22 @@ export function hydration_failed() {
}
}
/**
* Could not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`
* @returns {never}
*/
export function invalid_snippet() {
if (DEV) {
const error = new Error(`invalid_snippet\nCould not \`{@render}\` snippet due to the expression being \`null\` or \`undefined\`. Consider using optional chaining \`{@render snippet?.()}\``);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("invalid_snippet");
}
}
/**
* `%name%(...)` cannot be used in runes mode
* @param {string} name

@ -18,7 +18,7 @@ export { css_props } from './dom/blocks/css-props.js';
export { index, each } from './dom/blocks/each.js';
export { html } from './dom/blocks/html.js';
export { sanitize_slots, slot } from './dom/blocks/slot.js';
export { snippet, wrap_snippet, empty_snippet } from './dom/blocks/snippet.js';
export { snippet, wrap_snippet } from './dom/blocks/snippet.js';
export { component } from './dom/blocks/svelte-component.js';
export { element } from './dom/blocks/svelte-element.js';
export { head } from './dom/blocks/svelte-head.js';

@ -8,6 +8,6 @@ export default test({
assert.throws(() => {
btn?.click();
flushSync();
}, /snippet is not a function/);
}, /invalid_snippet/);
}
});

Loading…
Cancel
Save