aaa
Rich Harris 8 months ago
parent baba2638c9
commit ef59763c76

@ -613,7 +613,10 @@ function special(parser) {
type: 'HtmlTag', type: 'HtmlTag',
start, start,
end: parser.index, end: parser.index,
expression expression,
metadata: {
expression: create_expression_metadata()
}
}); });
return; return;

@ -15,5 +15,8 @@ export function HtmlTag(node, context) {
// unfortunately this is necessary in order to fix invalid HTML // unfortunately this is necessary in order to fix invalid HTML
mark_subtree_dynamic(context.path); mark_subtree_dynamic(context.path);
context.next(); context.next({
...context.state,
expression: node.metadata.expression
});
} }

@ -11,17 +11,38 @@ import * as b from '../../../../utils/builders.js';
export function HtmlTag(node, context) { export function HtmlTag(node, context) {
context.state.template.push('<!>'); context.state.template.push('<!>');
// push into init, so that bindings run afterwards, which might trigger another run and override hydration const { is_async } = node.metadata.expression;
context.state.init.push(
b.stmt( const expression = /** @type {Expression} */ (context.visit(node.expression));
b.call( const html = is_async ? b.call('$.get', b.id('$$html')) : expression;
'$.html',
context.state.node, const is_svg = context.state.metadata.namespace === 'svg';
b.thunk(/** @type {Expression} */ (context.visit(node.expression))), const is_mathml = context.state.metadata.namespace === 'mathml';
b.literal(context.state.metadata.namespace === 'svg'),
b.literal(context.state.metadata.namespace === 'mathml'), const statement = b.stmt(
is_ignored(node, 'hydration_html_changed') && b.true b.call(
) '$.html',
context.state.node,
b.thunk(html),
is_svg && b.true,
is_mathml && b.true,
is_ignored(node, 'hydration_html_changed') && b.true
) )
); );
// push into init, so that bindings run afterwards, which might trigger another run and override hydration
if (node.metadata.expression.is_async) {
context.state.init.push(
b.stmt(
b.call(
'$.async',
context.state.node,
b.array([b.thunk(expression, true)]),
b.arrow([context.state.node, b.id('$$html')], b.block([statement]))
)
)
);
} else {
context.state.init.push(statement);
}
} }

@ -135,6 +135,10 @@ export namespace AST {
export interface HtmlTag extends BaseNode { export interface HtmlTag extends BaseNode {
type: 'HtmlTag'; type: 'HtmlTag';
expression: Expression; expression: Expression;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
} }
/** An HTML comment */ /** An HTML comment */

@ -39,7 +39,7 @@ function check_hash(element, server_hash, value) {
* @param {boolean} [skip_warning] * @param {boolean} [skip_warning]
* @returns {void} * @returns {void}
*/ */
export function html(node, get_value, svg, mathml, skip_warning) { export function html(node, get_value, svg = false, mathml = false, skip_warning = false) {
var anchor = node; var anchor = node;
var value = ''; var value = '';

@ -0,0 +1,35 @@
import { flushSync, tick } from 'svelte';
import { deferred } from '../../../../src/internal/shared/utils.js';
import { test } from '../../test';
/** @type {ReturnType<typeof deferred>} */
let d;
export default test({
html: `<p>pending</p>`,
get props() {
d = deferred();
return {
promise: d.promise
};
},
async test({ assert, target, component }) {
d.resolve('hello');
await Promise.resolve();
await Promise.resolve();
await tick();
flushSync();
assert.htmlEqual(target.innerHTML, '<h1>hello</h1>');
component.promise = (d = deferred()).promise;
await tick();
assert.htmlEqual(target.innerHTML, '<p>pending</p>');
d.resolve('wheee');
await tick();
assert.htmlEqual(target.innerHTML, '<h1>wheee</h1>');
}
});

@ -0,0 +1,11 @@
<script>
let { promise } = $props();
</script>
<svelte:boundary>
<h1>{@html await promise}</h1>
{#snippet pending()}
<p>pending</p>
{/snippet}
</svelte:boundary>

@ -13,7 +13,7 @@ export default function Skip_static_subtree($$anchor, $$props) {
var node = $.sibling(h1, 10); var node = $.sibling(h1, 10);
$.html(node, () => $$props.content, false, false); $.html(node, () => $$props.content);
$.next(14); $.next(14);
$.reset(main); $.reset(main);

Loading…
Cancel
Save