move if block logic

pull/10542/head
Rich Harris 3 years ago
parent a279e802d5
commit 4363eccaca

@ -32,32 +32,6 @@ export function create_root_block(intro) {
};
}
/** @returns {import('./types.js').IfBlock} */
export function create_if_block() {
return {
// alternate transitions
a: null,
// alternate effect
ae: null,
// consequent transitions
c: null,
// consequent effect
ce: null,
// dom
d: null,
// effect
e: null,
// parent
p: /** @type {import('./types.js').Block} */ (current_block),
// transition
r: null,
// type
t: IF_BLOCK,
// value
v: false
};
}
/** @returns {import('./types.js').KeyBlock} */
export function create_key_block() {
return {

@ -0,0 +1,186 @@
import { IF_BLOCK } from '../../block.js';
import {
current_hydration_fragment,
hydrate_block_anchor,
hydrating,
set_current_hydration_fragment
} from '../../hydration.js';
import { remove } from '../../reconciler.js';
import {
current_block,
destroy_signal,
execute_effect,
push_destroy_fn,
render_effect
} from '../../runtime.js';
import { trigger_transitions } from '../../transitions.js';
/** @returns {import('../../types.js').IfBlock} */
function create_if_block() {
return {
// alternate transitions
a: null,
// alternate effect
ae: null,
// consequent transitions
c: null,
// consequent effect
ce: null,
// dom
d: null,
// effect
e: null,
// parent
p: /** @type {import('../../types.js').Block} */ (current_block),
// transition
r: null,
// type
t: IF_BLOCK,
// value
v: false
};
}
/**
* @param {Comment} anchor_node
* @param {() => boolean} condition_fn
* @param {(anchor: Node) => void} consequent_fn
* @param {null | ((anchor: Node) => void)} alternate_fn
* @returns {void}
*/
export default function (anchor_node, condition_fn, consequent_fn, alternate_fn) {
const block = create_if_block();
hydrate_block_anchor(anchor_node);
/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false;
/** @type {null | import('../../types.js').TemplateNode | Array<import('../../types.js').TemplateNode>} */
let consequent_dom = null;
/** @type {null | import('../../types.js').TemplateNode | Array<import('../../types.js').TemplateNode>} */
let alternate_dom = null;
let has_mounted = false;
/**
* @type {import('../../types.js').EffectSignal | null}
*/
let current_branch_effect = null;
const if_effect = render_effect(
() => {
const result = !!condition_fn();
if (block.v !== result || !has_mounted) {
block.v = result;
if (has_mounted) {
const consequent_transitions = block.c;
const alternate_transitions = block.a;
if (result) {
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'out');
}
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'in');
}
} else {
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'out');
}
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'in');
}
}
} 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();
}
}
has_mounted = true;
}
},
block,
false
);
// Managed effect
const consequent_effect = render_effect(
(
/** @type {any} */ _,
/** @type {import('../../types.js').EffectSignal | null} */ consequent_effect
) => {
const result = block.v;
if (!result && consequent_dom !== null) {
remove(consequent_dom);
consequent_dom = null;
}
if (result && current_branch_effect !== consequent_effect) {
consequent_fn(anchor_node);
if (mismatch && current_branch_effect === null) {
// Set fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
}
current_branch_effect = consequent_effect;
consequent_dom = block.d;
}
block.d = null;
},
block,
true
);
block.ce = consequent_effect;
// Managed effect
const alternate_effect = render_effect(
(
/** @type {any} */ _,
/** @type {import('../../types.js').EffectSignal | null} */ alternate_effect
) => {
const result = block.v;
if (result && alternate_dom !== null) {
remove(alternate_dom);
alternate_dom = null;
}
if (!result && current_branch_effect !== alternate_effect) {
if (alternate_fn !== null) {
alternate_fn(anchor_node);
}
if (mismatch && current_branch_effect === null) {
// Set fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
}
current_branch_effect = alternate_effect;
alternate_dom = block.d;
}
block.d = null;
},
block,
true
);
block.ae = alternate_effect;
push_destroy_fn(if_effect, () => {
if (consequent_dom !== null) {
remove(consequent_dom);
}
if (alternate_dom !== null) {
remove(alternate_dom);
}
destroy_signal(consequent_effect);
destroy_signal(alternate_effect);
});
block.e = if_effect;
}

@ -12,7 +12,6 @@ import {
} from './operations.js';
import {
create_root_block,
create_if_block,
create_key_block,
create_await_block,
create_dynamic_element_block,
@ -1453,151 +1452,6 @@ export function slot(anchor_node, slot_fn, slot_props, fallback_fn) {
}
}
/**
* @param {Comment} anchor_node
* @param {() => boolean} condition_fn
* @param {(anchor: Node) => void} consequent_fn
* @param {null | ((anchor: Node) => void)} alternate_fn
* @returns {void}
*/
function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
const block = create_if_block();
hydrate_block_anchor(anchor_node);
/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false;
/** @type {null | import('./types.js').TemplateNode | Array<import('./types.js').TemplateNode>} */
let consequent_dom = null;
/** @type {null | import('./types.js').TemplateNode | Array<import('./types.js').TemplateNode>} */
let alternate_dom = null;
let has_mounted = false;
/**
* @type {import("./types.js").EffectSignal | null}
*/
let current_branch_effect = null;
const if_effect = render_effect(
() => {
const result = !!condition_fn();
if (block.v !== result || !has_mounted) {
block.v = result;
if (has_mounted) {
const consequent_transitions = block.c;
const alternate_transitions = block.a;
if (result) {
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'out');
}
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'in');
}
} else {
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'out');
}
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'in');
}
}
} 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();
}
}
has_mounted = true;
}
},
block,
false
);
// Managed effect
const consequent_effect = render_effect(
(
/** @type {any} */ _,
/** @type {import("./types.js").EffectSignal | null} */ consequent_effect
) => {
const result = block.v;
if (!result && consequent_dom !== null) {
remove(consequent_dom);
consequent_dom = null;
}
if (result && current_branch_effect !== consequent_effect) {
consequent_fn(anchor_node);
if (mismatch && current_branch_effect === null) {
// Set fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
}
current_branch_effect = consequent_effect;
consequent_dom = block.d;
}
block.d = null;
},
block,
true
);
block.ce = consequent_effect;
// Managed effect
const alternate_effect = render_effect(
(
/** @type {any} */ _,
/** @type {import("./types.js").EffectSignal | null} */ alternate_effect
) => {
const result = block.v;
if (result && alternate_dom !== null) {
remove(alternate_dom);
alternate_dom = null;
}
if (!result && current_branch_effect !== alternate_effect) {
if (alternate_fn !== null) {
alternate_fn(anchor_node);
}
if (mismatch && current_branch_effect === null) {
// Set fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
}
current_branch_effect = alternate_effect;
alternate_dom = block.d;
}
block.d = null;
},
block,
true
);
block.ae = alternate_effect;
push_destroy_fn(if_effect, () => {
if (consequent_dom !== null) {
remove(consequent_dom);
}
if (alternate_dom !== null) {
remove(alternate_dom);
}
destroy_signal(consequent_effect);
destroy_signal(alternate_effect);
});
block.e = if_effect;
}
export { if_block as if };
/**
* @param {(anchor: Node | null) => void} render_fn
* @returns {void}

@ -40,6 +40,7 @@ export {
freeze,
init
} from './client/runtime.js';
export { default as if } from './client/dom/blocks/if.js';
export * from './client/each.js';
export * from './client/render.js';
export * from './client/validate.js';

Loading…
Cancel
Save