pull/12215/head
Rich Harris 2 years ago
parent 1a14f8c0b9
commit 27b38cdd9f

@ -1,5 +1,5 @@
import { derived } from '../../reactivity/deriveds.js'; import { derived } from '../../reactivity/deriveds.js';
import { render_effect } from '../../reactivity/effects.js'; import { block, branch, destroy_effect, render_effect } from '../../reactivity/effects.js';
import { get } from '../../runtime.js'; import { get } from '../../runtime.js';
import { is_array } from '../../utils.js'; import { is_array } from '../../utils.js';
import { hydrate_nodes, hydrating } from '../hydration.js'; import { hydrate_nodes, hydrating } from '../hydration.js';
@ -14,22 +14,53 @@ import { assign_nodes } from '../template.js';
* @returns {void} * @returns {void}
*/ */
export function html(anchor, get_value, svg, mathml) { export function html(anchor, get_value, svg, mathml) {
let value = derived(get_value); var value = '';
render_effect(() => { /** @type {import('#client').Effect | null} */
var dom = html_to_dom(anchor, get(value), svg, mathml); var effect;
if (dom) { block(anchor, 0, () => {
if (is_array(dom)) { if (value === (value = get_value())) return;
assign_nodes(dom[0], dom[dom.length - 1]);
} else { if (effect) {
assign_nodes(dom, dom); destroy_effect(effect);
effect = null;
} }
return () => { if (value === '') return;
remove(dom);
}; effect = branch(() => {
if (hydrating) {
assign_nodes(hydrate_nodes[0], hydrate_nodes[hydrate_nodes.length - 1]);
return;
} }
var html = value + '';
if (svg) html = `<svg>${html}</svg>`;
else if (mathml) html = `<math>${html}</math>`;
// Don't use create_fragment_with_script_from_html here because that would mean script tags are executed.
// @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons.
/** @type {DocumentFragment | Element} */
var node = create_fragment_from_html(html);
if (svg || mathml) {
node = /** @type {Element} */ (node.firstChild);
}
assign_nodes(
/** @type {import('#client').TemplateNode} */ (node.firstChild),
/** @type {import('#client').TemplateNode} */ (node.lastChild)
);
if (svg || mathml) {
while (node.firstChild) {
anchor.before(node.firstChild);
}
} else {
anchor.before(node);
}
});
}); });
} }
@ -37,13 +68,13 @@ export function html(anchor, get_value, svg, mathml) {
* Creates the content for a `@html` tag from its string value, * Creates the content for a `@html` tag from its string value,
* inserts it before the target anchor and returns the new nodes. * inserts it before the target anchor and returns the new nodes.
* @template V * @template V
* @param {Element | Text | Comment} target * @param {Element | Text | Comment} anchor
* @param {V} value * @param {V} value
* @param {boolean} svg * @param {boolean} svg
* @param {boolean} mathml * @param {boolean} mathml
* @returns {Element | Comment | (Element | Comment | Text)[]} * @returns {Element | Comment | (Element | Comment | Text)[]}
*/ */
function html_to_dom(target, value, svg, mathml) { function html_to_dom(anchor, value, svg, mathml) {
if (hydrating) return hydrate_nodes; if (hydrating) return hydrate_nodes;
var html = value + ''; var html = value + '';
@ -61,7 +92,7 @@ function html_to_dom(target, value, svg, mathml) {
if (node.childNodes.length === 1) { if (node.childNodes.length === 1) {
var child = /** @type {Text | Element | Comment} */ (node.firstChild); var child = /** @type {Text | Element | Comment} */ (node.firstChild);
target.before(child); anchor.before(child);
return child; return child;
} }
@ -69,10 +100,10 @@ function html_to_dom(target, value, svg, mathml) {
if (svg || mathml) { if (svg || mathml) {
while (node.firstChild) { while (node.firstChild) {
target.before(node.firstChild); anchor.before(node.firstChild);
} }
} else { } else {
target.before(node); anchor.before(node);
} }
return nodes; return nodes;

@ -85,11 +85,15 @@ export function first_child(fragment, is_text) {
// text node to hydrate — we must therefore create one // text node to hydrate — we must therefore create one
if (is_text && hydrate_start?.nodeType !== 3) { if (is_text && hydrate_start?.nodeType !== 3) {
var text = empty(); var text = empty();
var dom = /** @type {import('#client').TemplateNode[]} */ ( // var dom = /** @type {import('#client').TemplateNode[]} */ (
/** @type {import('#client').Effect} */ (current_effect).dom // /** @type {import('#client').Effect} */ (current_effect).dom
); // );
dom.unshift(text); if (current_effect.nodes.start === hydrate_start) {
current_effect.nodes.start = text;
}
// dom.unshift(text);
hydrate_start?.before(text); hydrate_start?.before(text);
return text; return text;
@ -126,6 +130,8 @@ export function sibling(node, is_text = false) {
/** @type {import('#client').Effect} */ (current_effect).dom /** @type {import('#client').Effect} */ (current_effect).dom
); );
// TODO something needs to happen here but i'm not quite sure what
dom.unshift(text); dom.unshift(text);
next_sibling?.before(text); next_sibling?.before(text);

@ -121,7 +121,7 @@ function create_effect(type, fn, sync) {
sync && sync &&
effect.deps === null && effect.deps === null &&
effect.first === null && effect.first === null &&
effect.dom === null && effect.nodes === null &&
effect.teardown === null; effect.teardown === null;
if (!inert && !is_root) { if (!inert && !is_root) {
@ -339,8 +339,6 @@ export function execute_effect_teardown(effect) {
* @returns {void} * @returns {void}
*/ */
export function destroy_effect(effect, remove_dom = true) { export function destroy_effect(effect, remove_dom = true) {
var dom = effect.dom;
var removed = false; var removed = false;
if (remove_dom) { if (remove_dom) {
@ -351,10 +349,6 @@ export function destroy_effect(effect, remove_dom = true) {
removed = true; removed = true;
} }
if (dom !== null && remove_dom) {
// remove(dom);
}
destroy_effect_children(effect, remove_dom && !removed); destroy_effect_children(effect, remove_dom && !removed);
remove_reactions(effect, 0); remove_reactions(effect, 0);
set_signal_status(effect, DESTROYED); set_signal_status(effect, DESTROYED);
@ -379,7 +373,6 @@ export function destroy_effect(effect, remove_dom = true) {
effect.prev = effect.prev =
effect.teardown = effect.teardown =
effect.ctx = effect.ctx =
effect.dom =
effect.deps = effect.deps =
effect.parent = effect.parent =
effect.fn = effect.fn =

Loading…
Cancel
Save