pull/10798/head
Rich Harris 2 years ago
parent 776fe8b33b
commit 74cf046c45

@ -1,4 +1,4 @@
import { IF_BLOCK } from '../../constants.js';
import { IF_BLOCK, UNINITIALIZED } from '../../constants.js';
import {
current_hydration_fragment,
hydrate_block_anchor,
@ -53,132 +53,108 @@ export function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn)
/** @type {null | import('#client').TemplateNode | Array<import('#client').TemplateNode>} */
let alternate_dom = null;
let has_mounted = false;
/**
* @type {import('#client').Effect | null}
*/
let current_branch_effect = null;
/** @type {import('#client').Effect | null} */
let consequent_effect;
let consequent_effect = null;
/** @type {import('#client').Effect | null} */
let alternate_effect;
function create_consequent_effect() {
return render_effect(
() => {
consequent_fn(anchor_node);
if (mismatch && current_branch_effect === null) {
set_current_hydration_fragment([]);
}
consequent_dom = block.d;
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (consequent_dom !== null) {
remove(consequent_dom);
consequent_dom = null;
}
};
},
block,
true
);
}
function create_alternate_effect() {
return render_effect(
() => {
/** @type {((anchor: Node) => void)} */ (alternate_fn)(anchor_node);
if (mismatch && current_branch_effect === null) {
set_current_hydration_fragment([]);
}
alternate_dom = block.d;
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (alternate_dom !== null) {
remove(alternate_dom);
alternate_dom = null;
}
};
},
block,
true
);
}
let alternate_effect = null;
/** @type {boolean | null} */
let condition = null;
const if_effect = render_effect(() => {
const result = !!condition_fn();
if (block.v !== result || !has_mounted) {
block.v = result;
if (has_mounted) {
if (result) {
if (consequent_effect) {
resume_effect(consequent_effect);
} else {
consequent_effect = create_consequent_effect();
}
if (alternate_effect) {
pause_effect(alternate_effect, () => {
alternate_effect = null;
if (alternate_dom) remove(alternate_dom);
});
}
} else {
if (alternate_effect) {
resume_effect(alternate_effect);
} else if (alternate_fn) {
alternate_effect = create_alternate_effect();
}
if (consequent_effect) {
pause_effect(consequent_effect, () => {
consequent_effect = null;
if (consequent_dom) remove(consequent_dom);
});
}
}
if (condition === (condition = !!condition_fn())) return;
if (hydrating) {
const comment_text = /** @type {Comment} */ (current_hydration_fragment?.[0])?.data;
if (
!comment_text ||
(comment_text === 'ssr:if:true' && !condition) ||
(comment_text === 'ssr:if:false' && condition)
) {
// Hydration mismatch: remove everything inside the anchor and start fresh.
// This could happen using when `{#if browser} .. {/if}` in SvelteKit.
remove(current_hydration_fragment);
set_current_hydration_fragment(null);
mismatch = true;
} else {
// Remove the ssr:if comment node or else it will confuse the subsequent hydration algorithm
current_hydration_fragment.shift();
}
}
if (condition) {
if (consequent_effect) {
resume_effect(consequent_effect);
} else {
if (hydrating) {
const comment_text = /** @type {Comment} */ (current_hydration_fragment?.[0])?.data;
if (
!comment_text ||
(comment_text === 'ssr:if:true' && !result) ||
(comment_text === 'ssr:if:false' && result)
) {
// Hydration mismatch: remove everything inside the anchor and start fresh.
// This could happen using when `{#if browser} .. {/if}` in SvelteKit.
remove(current_hydration_fragment);
set_current_hydration_fragment(null);
mismatch = true;
} else {
// Remove the ssr:if comment node or else it will confuse the subsequent hydration algorithm
current_hydration_fragment.shift();
}
}
if (result) {
consequent_effect ??= create_consequent_effect();
} else if (alternate_fn) {
alternate_effect ??= create_alternate_effect();
}
consequent_effect = render_effect(
() => {
consequent_fn(anchor_node);
consequent_dom = block.d;
if (mismatch) {
set_current_hydration_fragment([]);
}
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (consequent_dom !== null) {
remove(consequent_dom);
consequent_dom = null;
}
};
},
block,
true
);
}
if (alternate_effect) {
pause_effect(alternate_effect, () => {
alternate_effect = null;
if (alternate_dom) remove(alternate_dom);
});
}
} else {
if (alternate_effect) {
resume_effect(alternate_effect);
} else if (alternate_fn) {
alternate_effect = render_effect(
() => {
alternate_fn(anchor_node);
alternate_dom = block.d;
if (mismatch) {
set_current_hydration_fragment([]);
}
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (alternate_dom !== null) {
remove(alternate_dom);
alternate_dom = null;
}
};
},
block,
true
);
}
has_mounted = true;
if (consequent_effect) {
pause_effect(consequent_effect, () => {
consequent_effect = null;
if (consequent_dom) remove(consequent_dom);
});
}
}
}, block);
mismatch = false; // TODO not sure if we actually need this — belt and braces
if_effect.ondestroy = () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown

Loading…
Cancel
Save