aaa
Rich Harris 8 months ago
parent baba2638c9
commit ef59763c76

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

@ -15,5 +15,8 @@ export function HtmlTag(node, context) {
// unfortunately this is necessary in order to fix invalid HTML
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) {
context.state.template.push('<!>');
const { is_async } = node.metadata.expression;
const expression = /** @type {Expression} */ (context.visit(node.expression));
const html = is_async ? b.call('$.get', b.id('$$html')) : expression;
const is_svg = context.state.metadata.namespace === 'svg';
const is_mathml = context.state.metadata.namespace === 'mathml';
const statement = b.stmt(
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(
'$.html',
'$.async',
context.state.node,
b.thunk(/** @type {Expression} */ (context.visit(node.expression))),
b.literal(context.state.metadata.namespace === 'svg'),
b.literal(context.state.metadata.namespace === 'mathml'),
is_ignored(node, 'hydration_html_changed') && b.true
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 {
type: 'HtmlTag';
expression: Expression;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
/** An HTML comment */

@ -39,7 +39,7 @@ function check_hash(element, server_hash, value) {
* @param {boolean} [skip_warning]
* @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 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);
$.html(node, () => $$props.content, false, false);
$.html(node, () => $$props.content);
$.next(14);
$.reset(main);

Loading…
Cancel
Save