Socket
Socket
Sign inDemoInstall

svelte

Package Overview
Dependencies
18
Maintainers
3
Versions
617
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.0-next.82 to 5.0.0-next.83

2

package.json

@@ -5,3 +5,3 @@ {

"license": "MIT",
"version": "5.0.0-next.82",
"version": "5.0.0-next.83",
"type": "module",

@@ -8,0 +8,0 @@ "types": "./types/index.d.ts",

@@ -955,21 +955,2 @@ import is_reference from 'is-reference';

// Check for selector() API calls
if (callee.type === 'MemberExpression' && callee.object.type === 'Identifier') {
const binding = context.state.scope.get(callee.object.name);
const selector_binding = context.state.scope.get('selector');
if (
selector_binding !== null &&
selector_binding.declaration_kind === 'import' &&
selector_binding.initial !== null &&
selector_binding.initial.type === 'ImportDeclaration' &&
selector_binding.initial.source.value === 'svelte' &&
binding !== null &&
binding.initial !== null &&
binding.initial.type === 'CallExpression' &&
binding.initial.callee.type === 'Identifier' &&
binding.initial.callee.name === 'selector'
) {
return true;
}
}
// String / Number / BigInt / Boolean casting calls

@@ -976,0 +957,0 @@ if (callee.type === 'Identifier') {

@@ -12,4 +12,3 @@ import { is_promise } from '../../../common.js';

import { destroy_effect, pause_effect, render_effect } from '../../reactivity/effects.js';
import { DESTROYED, INERT } from '../../constants.js';
import { create_block } from './utils.js';
import { INERT } from '../../constants.js';

@@ -26,4 +25,2 @@ /**

export function await_block(anchor, get_input, pending_fn, then_fn, catch_fn) {
const block = create_block();
const component_context = current_component_context;

@@ -53,3 +50,3 @@

set_current_component_context(component_context);
var effect = render_effect(() => fn(anchor, value), {}, true);
var effect = render_effect(() => fn(anchor, value), true);
set_current_component_context(null);

@@ -66,14 +63,2 @@ set_current_reaction(null);

/** @param {import('#client').Effect} effect */
function pause(effect) {
if ((effect.f & DESTROYED) !== 0) return;
const block = effect.block;
pause_effect(effect, () => {
// TODO make this unnecessary
const dom = block?.d;
if (dom) remove(dom);
});
}
const branch = render_effect(() => {

@@ -87,11 +72,11 @@ if (input === (input = get_input())) return;

if (pending_effect && (pending_effect.f & INERT) === 0) {
if (pending_effect.block?.d) remove(pending_effect.block.d);
if (pending_effect.dom) remove(pending_effect.dom);
destroy_effect(pending_effect);
}
pending_effect = render_effect(() => pending_fn(anchor), {}, true);
pending_effect = render_effect(() => pending_fn(anchor), true);
}
if (then_effect) pause(then_effect);
if (catch_effect) pause(catch_effect);
if (then_effect) pause_effect(then_effect);
if (catch_effect) pause_effect(catch_effect);

@@ -101,3 +86,3 @@ promise.then(

if (promise !== input) return;
if (pending_effect) pause(pending_effect);
if (pending_effect) pause_effect(pending_effect);

@@ -110,3 +95,3 @@ if (then_fn) {

if (promise !== input) return;
if (pending_effect) pause(pending_effect);
if (pending_effect) pause_effect(pending_effect);

@@ -119,22 +104,22 @@ if (catch_fn) {

} else {
if (pending_effect) pause(pending_effect);
if (catch_effect) pause(catch_effect);
if (pending_effect) pause_effect(pending_effect);
if (catch_effect) pause_effect(catch_effect);
if (then_fn) {
if (then_effect) {
if (then_effect.block?.d) remove(then_effect.block.d);
if (then_effect.dom) remove(then_effect.dom);
destroy_effect(then_effect);
}
then_effect = render_effect(() => then_fn(anchor, input), {}, true);
then_effect = render_effect(() => then_fn(anchor, input), true);
}
}
}, block);
});
branch.ondestroy = () => {
// TODO this sucks, tidy it up
if (pending_effect?.block?.d) remove(pending_effect.block.d);
if (then_effect?.block?.d) remove(then_effect.block.d);
if (catch_effect?.block?.d) remove(catch_effect.block.d);
if (pending_effect?.dom) remove(pending_effect.dom);
if (then_effect?.dom) remove(then_effect.dom);
if (catch_effect?.dom) remove(catch_effect.dom);
};
}
import { namespace_svg } from '../../../../constants.js';
import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../hydration.js';
import { hydrate_nodes, hydrate_block_anchor, hydrating } from '../hydration.js';
import { empty } from '../operations.js';

@@ -18,3 +18,3 @@ import { render_effect } from '../../reactivity/effects.js';

/** @type {HTMLElement | SVGElement} */
let tag;
let element;

@@ -26,16 +26,15 @@ /** @type {Text | Comment} */

// Hydration: css props element is surrounded by a ssr comment ...
tag = /** @type {HTMLElement | SVGElement} */ (current_hydration_fragment[0]);
element = /** @type {HTMLElement | SVGElement} */ (hydrate_nodes[0]);
// ... and the child(ren) of the css props element is also surround by a ssr comment
component_anchor = /** @type {Comment} */ (tag.firstChild);
component_anchor = /** @type {Comment} */ (element.firstChild);
} else {
if (is_html) {
tag = document.createElement('div');
tag.style.display = 'contents';
element = document.createElement('div');
element.style.display = 'contents';
} else {
tag = document.createElementNS(namespace_svg, 'g');
element = document.createElementNS(namespace_svg, 'g');
}
anchor.before(tag);
component_anchor = empty();
tag.appendChild(component_anchor);
anchor.before(element);
component_anchor = element.appendChild(empty());
}

@@ -53,3 +52,3 @@

if (!(key in next_props)) {
tag.style.removeProperty(key);
element.style.removeProperty(key);
}

@@ -59,3 +58,3 @@ }

for (const key in next_props) {
tag.style.setProperty(key, next_props[key]);
element.style.setProperty(key, next_props[key]);
}

@@ -67,4 +66,4 @@

effect.ondestroy = () => {
remove(tag);
remove(element);
};
}

@@ -10,7 +10,7 @@ import {

import {
current_hydration_fragment,
get_hydration_fragment,
hydrate_nodes,
hydrate_block_anchor,
hydrating,
set_current_hydration_fragment
set_hydrating,
update_hydrate_nodes
} from '../hydration.js';

@@ -23,2 +23,3 @@ import { empty } from '../operations.js';

pause_effect,
pause_effects,
render_effect,

@@ -31,6 +32,5 @@ resume_effect,

import { STATE_SYMBOL } from '../../constants.js';
import { create_block } from './utils.js';
var NEW_BLOCK = -1;
var LIS_BLOCK = -2;
var NEW_ITEM = -1;
var LIS_ITEM = -2;

@@ -42,7 +42,7 @@ /**

*/
export let current_each_item_block = null;
export let current_each_item = null;
/** @param {import('#client').EachItem | null} block */
export function set_current_each_item_block(block) {
current_each_item_block = block;
/** @param {import('#client').EachItem | null} item */
export function set_current_each_item(item) {
current_each_item = item;
}

@@ -57,3 +57,3 @@

* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn
* @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn

@@ -63,4 +63,2 @@ * @returns {void}

function each(anchor, get_collection, flags, get_key, render_fn, fallback_fn, reconcile_fn) {
var block = create_block();
/** @type {import('#client').EachState} */

@@ -80,128 +78,116 @@ var state = { flags, items: [] };

var effect = render_effect(
() => {
var collection = get_collection();
var effect = render_effect(() => {
var collection = get_collection();
var array = is_array(collection)
? collection
: collection == null
? []
: Array.from(collection);
var array = is_array(collection)
? collection
: collection == null
? []
: Array.from(collection);
var keys = get_key === null ? array : array.map(get_key);
var keys = get_key === null ? array : array.map(get_key);
var length = array.length;
var length = array.length;
// If we are working with an array that isn't proxied or frozen, then remove strict equality and ensure the items
// are treated as reactive, so they get wrapped in a signal.
var flags = state.flags;
if ((flags & EACH_IS_STRICT_EQUALS) !== 0 && !is_frozen(array) && !(STATE_SYMBOL in array)) {
flags ^= EACH_IS_STRICT_EQUALS;
// If we are working with an array that isn't proxied or frozen, then remove strict equality and ensure the items
// are treated as reactive, so they get wrapped in a signal.
var flags = state.flags;
if ((flags & EACH_IS_STRICT_EQUALS) !== 0 && !is_frozen(array) && !(STATE_SYMBOL in array)) {
flags ^= EACH_IS_STRICT_EQUALS;
// Additionally if we're in an keyed each block, we'll need ensure the items are all wrapped in signals.
if ((flags & EACH_KEYED) !== 0 && (flags & EACH_ITEM_REACTIVE) === 0) {
flags ^= EACH_ITEM_REACTIVE;
}
// Additionally if we're in an keyed each block, we'll need ensure the items are all wrapped in signals.
if ((flags & EACH_KEYED) !== 0 && (flags & EACH_ITEM_REACTIVE) === 0) {
flags ^= EACH_ITEM_REACTIVE;
}
}
/** `true` if there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false;
/** `true` if there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false;
if (hydrating) {
var is_else =
/** @type {Comment} */ (current_hydration_fragment?.[0])?.data === 'ssr:each_else';
if (hydrating) {
var is_else = /** @type {Comment} */ (hydrate_nodes?.[0])?.data === 'ssr:each_else';
if (is_else !== (length === 0)) {
// hydration mismatch — remove the server-rendered DOM and start over
remove(current_hydration_fragment);
set_current_hydration_fragment(null);
mismatch = true;
} else if (is_else) {
// Remove the each_else comment node or else it will confuse the subsequent hydration algorithm
/** @type {import('#client').TemplateNode[]} */ (current_hydration_fragment).shift();
}
if (is_else !== (length === 0)) {
// hydration mismatch — remove the server-rendered DOM and start over
remove(hydrate_nodes);
set_hydrating(false);
mismatch = true;
} else if (is_else) {
// Remove the each_else comment node or else it will confuse the subsequent hydration algorithm
/** @type {import('#client').TemplateNode[]} */ (hydrate_nodes).shift();
}
}
// this is separate to the previous block because `hydrating` might change
if (hydrating) {
var b_blocks = [];
// this is separate to the previous block because `hydrating` might change
if (hydrating) {
var b_items = [];
// Hydrate block
var hydration_list = /** @type {import('#client').TemplateNode[]} */ (
current_hydration_fragment
);
var hydrating_node = hydration_list[0];
// Hydrate block
var hydration_list = /** @type {import('#client').TemplateNode[]} */ (hydrate_nodes);
var hydrating_node = hydration_list[0];
for (var i = 0; i < length; i++) {
var fragment = get_hydration_fragment(hydrating_node);
set_current_hydration_fragment(fragment);
if (!fragment) {
// If fragment is null, then that means that the server rendered less items than what
// the client code specifies -> break out and continue with client-side node creation
mismatch = true;
break;
}
for (var i = 0; i < length; i++) {
var nodes = update_hydrate_nodes(hydrating_node);
b_blocks[i] = create_item(array[i], keys?.[i], i, render_fn, flags);
// TODO helperise this
hydrating_node = /** @type {import('#client').TemplateNode} */ (
/** @type {Node} */ (
/** @type {Node} */ (fragment[fragment.length - 1] || hydrating_node).nextSibling
).nextSibling
);
if (nodes === null) {
// If `nodes` is null, then that means that the server rendered fewer items than what
// expected, so break out and continue appending non-hydrated items
mismatch = true;
set_hydrating(false);
break;
}
remove_excess_hydration_nodes(hydration_list, hydrating_node);
b_items[i] = create_item(array[i], keys?.[i], i, render_fn, flags);
state.items = b_blocks;
// TODO helperise this
hydrating_node = /** @type {import('#client').TemplateNode} */ (
/** @type {Node} */ (
/** @type {Node} */ (nodes[nodes.length - 1] || hydrating_node).nextSibling
).nextSibling
);
}
if (!hydrating) {
// TODO add 'empty controlled block' optimisation here
reconcile_fn(array, state, anchor, render_fn, flags, keys);
}
remove_excess_hydration_nodes(hydration_list, hydrating_node);
if (fallback_fn !== null) {
if (length === 0) {
if (fallback) {
resume_effect(fallback);
} else {
fallback = render_effect(
() => {
fallback_fn(anchor);
var dom = block.d; // TODO would be nice if this was just returned from the managed effect function...
state.items = b_items;
}
return () => {
if (dom !== null) {
remove(dom);
dom = null;
}
};
},
block,
true
);
}
} else if (fallback !== null) {
pause_effect(fallback, () => {
fallback = null;
});
if (!hydrating) {
// TODO add 'empty controlled block' optimisation here
reconcile_fn(array, state, anchor, render_fn, flags, keys);
}
if (fallback_fn !== null) {
if (length === 0) {
if (fallback) {
resume_effect(fallback);
} else {
fallback = render_effect(() => {
var dom = fallback_fn(hydrating ? null : anchor);
return () => {
if (dom !== undefined) {
remove(dom);
}
};
}, true);
}
} else if (fallback !== null) {
pause_effect(fallback, () => {
fallback = null;
});
}
}
if (mismatch) {
// Set a fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
}
},
block,
false
);
if (mismatch) {
// continue in hydration mode
set_hydrating(true);
}
});
effect.ondestroy = () => {
for (var item of state.items) {
if (item.d !== null) {
if (item.e.dom !== null) {
remove(item.e.dom);
destroy_effect(item.e);
remove(item.d);
}

@@ -221,3 +207,3 @@ }

* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn
* @returns {void}

@@ -235,3 +221,3 @@ */

* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn
* @returns {void}

@@ -286,22 +272,10 @@ */

// remove items
var remaining = a - b;
var effects = [];
for (i = b; i < a; i += 1) {
effects.push(a_items[i].e);
}
var clear = () => {
for (var i = b; i < a; i += 1) {
var block = a_items[i];
if (block.d) remove(block.d);
}
pause_effects(effects, () => {
state.items.length = b;
};
var check = () => {
if (--remaining === 0) {
clear();
}
};
for (; i < a; i += 1) {
pause_effect(a_items[i].e, check);
}
});
}

@@ -324,9 +298,9 @@ }

function reconcile_tracked_array(array, state, anchor, render_fn, flags, keys) {
var a_blocks = state.items;
var a_items = state.items;
var a = a_blocks.length;
var a = a_items.length;
var b = array.length;
/** @type {Array<import('#client').EachItem>} */
var b_blocks = Array(b);
var b_items = Array(b);

@@ -336,16 +310,16 @@ var is_animated = (flags & EACH_IS_ANIMATED) !== 0;

var start = 0;
var block;
var item;
/** @type {Array<import('#client').EachItem>} */
/** @type {import('#client').Effect[]} */
var to_destroy = [];
// Step 1 — trim common suffix
while (a > 0 && b > 0 && a_blocks[a - 1].k === keys[b - 1]) {
block = b_blocks[--b] = a_blocks[--a];
anchor = get_first_child(block);
while (a > 0 && b > 0 && a_items[a - 1].k === keys[b - 1]) {
item = b_items[--b] = a_items[--a];
anchor = get_first_child(item);
resume_effect(block.e);
resume_effect(item.e);
if (should_update) {
update_item(block, array[b], b, flags);
update_item(item, array[b], b, flags);
}

@@ -355,9 +329,9 @@ }

// Step 2 — trim common prefix
while (start < a && start < b && a_blocks[start].k === keys[start]) {
block = b_blocks[start] = a_blocks[start];
while (start < a && start < b && a_items[start].k === keys[start]) {
item = b_items[start] = a_items[start];
resume_effect(block.e);
resume_effect(item.e);
if (should_update) {
update_item(block, array[start], start, flags);
update_item(item, array[start], start, flags);
}

@@ -372,5 +346,5 @@

while (start < b) {
block = create_item(array[start], keys[start], start, render_fn, flags);
b_blocks[start++] = block;
insert_item(block, anchor);
item = create_item(array[start], keys[start], start, render_fn, flags);
b_items[start++] = item;
insert_item(item, anchor);
}

@@ -380,3 +354,3 @@ } else if (start === b) {

while (start < a) {
to_destroy.push(a_blocks[start++]);
to_destroy.push(a_items[start++].e);
}

@@ -390,8 +364,8 @@ } else {

var index;
var last_block;
var last_item;
var last_sibling;
// store the indexes of each block in the new world
// store the indexes of each item in the new world
for (i = start; i < b; i += 1) {
sources[i - start] = NEW_BLOCK;
sources[i - start] = NEW_ITEM;
map_set(indexes, keys[i], i);

@@ -403,10 +377,10 @@ }

if (is_animated) {
// for all blocks that were in both the old and the new list,
// for all items that were in both the old and the new list,
// measure them and store them in `to_animate` so we can
// apply animations once the DOM has been updated
for (i = 0; i < a_blocks.length; i += 1) {
block = a_blocks[i];
if (indexes.has(block.k)) {
block.a?.measure();
to_animate.push(block);
for (i = 0; i < a_items.length; i += 1) {
item = a_items[i];
if (indexes.has(item.k)) {
item.a?.measure();
to_animate.push(item);
}

@@ -416,19 +390,19 @@ }

// populate the `sources` array for each old block with
// populate the `sources` array for each old item with
// its new index, so that we can calculate moves
for (i = start; i < a; i += 1) {
block = a_blocks[i];
index = map_get(indexes, block.k);
item = a_items[i];
index = map_get(indexes, item.k);
resume_effect(block.e);
resume_effect(item.e);
if (index === undefined) {
to_destroy.push(block);
to_destroy.push(item.e);
} else {
moved = true;
sources[index - start] = i;
b_blocks[index] = block;
b_items[index] = item;
if (is_animated) {
to_animate.push(block);
to_animate.push(item);
}

@@ -438,3 +412,3 @@ }

// if we need to move blocks (as opposed to just adding/removing),
// if we need to move items (as opposed to just adding/removing),
// figure out how to do so efficiently (I would be lying if I said

@@ -446,22 +420,22 @@ // I fully understand this part)

// working from the back, insert new or moved blocks
// working from the back, insert new or moved items
while (b-- > start) {
index = sources[b - start];
var insert = index === NEW_BLOCK;
var insert = index === NEW_ITEM;
if (insert) {
block = create_item(array[b], keys[b], b, render_fn, flags);
item = create_item(array[b], keys[b], b, render_fn, flags);
} else {
block = b_blocks[b];
item = b_items[b];
if (should_update) {
update_item(block, array[b], b, flags);
update_item(item, array[b], b, flags);
}
}
if (insert || (moved && index !== LIS_BLOCK)) {
last_sibling = last_block === undefined ? anchor : get_first_child(last_block);
anchor = insert_item(block, last_sibling);
if (insert || (moved && index !== LIS_ITEM)) {
last_sibling = last_item === undefined ? anchor : get_first_child(last_item);
anchor = insert_item(item, last_sibling);
}
last_block = b_blocks[b] = block;
last_item = b_items[b] = item;
}

@@ -476,4 +450,4 @@

untrack(() => {
for (block of to_animate) {
block.a?.apply();
for (item of to_animate) {
item.a?.apply();
}

@@ -485,24 +459,5 @@ });

var remaining = to_destroy.length;
if (remaining > 0) {
var clear = () => {
for (block of to_destroy) {
if (block.d) remove(block.d);
}
state.items = b_blocks;
};
var check = () => {
if (--remaining === 0) {
clear();
}
};
for (block of to_destroy) {
pause_effect(block.e, check);
}
} else {
state.items = b_blocks;
}
pause_effects(to_destroy, () => {
state.items = b_items;
});
}

@@ -549,3 +504,3 @@

// Skip -1 values at the start of the input array `a`.
for (; a[i] === NEW_BLOCK; ++i) {
for (; a[i] === NEW_ITEM; ++i) {
/**/

@@ -559,3 +514,3 @@ }

if (k !== NEW_BLOCK) {
if (k !== NEW_ITEM) {
// Ignore -1 values.

@@ -594,3 +549,3 @@ j = index[index_length];

while (index_length-- >= 0) {
a[j] = LIS_BLOCK;
a[j] = LIS_ITEM;
j = parent[j];

@@ -601,17 +556,17 @@ }

/**
* @param {import('#client').EachItem} block
* @param {Text | Element | Comment} sibling
* @param {import('#client').EachItem} item
* @param {Text | Element | Comment} anchor
* @returns {Text | Element | Comment}
*/
function insert_item(block, sibling) {
var current = /** @type {import('#client').TemplateNode} */ (block.d);
return insert(current, sibling);
function insert_item(item, anchor) {
var current = /** @type {import('#client').Dom} */ (item.e.dom);
return insert(current, anchor);
}
/**
* @param {import('#client').EachItem} block
* @param {import('#client').EachItem} item
* @returns {Text | Element | Comment}
*/
function get_first_child(block) {
var current = block.d;
function get_first_child(item) {
var current = item.e.dom;

@@ -626,4 +581,4 @@ if (is_array(current)) {

/**
* @param {import('#client').EachItem} block
* @param {any} item
* @param {import('#client').EachItem} item
* @param {any} value
* @param {number} index

@@ -633,11 +588,11 @@ * @param {number} type

*/
function update_item(block, item, index, type) {
function update_item(item, value, index, type) {
if ((type & EACH_ITEM_REACTIVE) !== 0) {
set(block.v, item);
set(item.v, value);
}
if ((type & EACH_INDEX_REACTIVE) !== 0) {
set(/** @type {import('#client').Value<number>} */ (block.i), index);
set(/** @type {import('#client').Value<number>} */ (item.i), index);
} else {
block.i = index;
item.i = index;
}

@@ -648,3 +603,3 @@ }

* @template V
* @param {V} item
* @param {V} value
* @param {unknown} key

@@ -656,17 +611,9 @@ * @param {number} index

*/
function create_item(item, key, index, render_fn, flags) {
function create_item(value, key, index, render_fn, flags) {
var each_item_not_reactive = (flags & EACH_ITEM_REACTIVE) === 0;
var item_value = each_item_not_reactive
? item
: (flags & EACH_IS_STRICT_EQUALS) !== 0
? source(item)
: mutable_source(item);
/** @type {import('#client').EachItem} */
var block = {
var item = {
a: null,
// dom
d: null,
// effect
// @ts-expect-error

@@ -679,22 +626,28 @@ e: null,

// item
v: item_value
v: each_item_not_reactive
? value
: (flags & EACH_IS_STRICT_EQUALS) !== 0
? source(value)
: mutable_source(value)
};
var previous_each_item_block = current_each_item_block;
var previous_each_item = current_each_item;
try {
current_each_item_block = block;
current_each_item = item;
block.e = render_effect(
() => {
render_fn(null, block.v, block.i);
},
block,
true
);
item.e = render_effect(() => {
var dom = render_fn(null, item.v, item.i);
return block;
return () => {
if (dom !== undefined) {
remove(dom);
}
};
}, true);
return item;
} finally {
current_each_item_block = previous_each_item_block;
current_each_item = previous_each_item;
}
}
import { IS_ELSEIF } from '../../constants.js';
import {
current_hydration_fragment,
hydrate_block_anchor,
hydrating,
set_current_hydration_fragment
} from '../hydration.js';
import { hydrate_nodes, hydrate_block_anchor, hydrating, set_hydrating } from '../hydration.js';
import { remove } from '../reconciler.js';

@@ -15,3 +10,2 @@ import {

} from '../../reactivity/effects.js';
import { create_block } from './utils.js';

@@ -22,17 +16,15 @@ /**

* @param {(anchor: Node) => import('#client').Dom} consequent_fn
* @param {null | ((anchor: Node) => import('#client').Dom)} alternate_fn
* @param {null | ((anchor: Node) => import('#client').Dom)} [alternate_fn]
* @param {boolean} [elseif] True if this is an `{:else if ...}` block rather than an `{#if ...}`, as that affects which transitions are considered 'local'
* @returns {void}
*/
export function if_block(anchor, get_condition, consequent_fn, alternate_fn, elseif = false) {
const block = create_block();
export function if_block(
anchor,
get_condition,
consequent_fn,
alternate_fn = null,
elseif = false
) {
hydrate_block_anchor(anchor);
/** @type {undefined | import('#client').Dom} */
let consequent_dom;
/** @type {undefined | import('#client').Dom} */
let alternate_dom;
/** @type {import('#client').Effect | null} */

@@ -54,3 +46,3 @@ let consequent_effect = null;

if (hydrating) {
const comment_text = /** @type {Comment} */ (current_hydration_fragment?.[0])?.data;
const comment_text = /** @type {Comment} */ (hydrate_nodes?.[0])?.data;

@@ -64,8 +56,8 @@ if (

// This could happen using when `{#if browser} .. {/if}` in SvelteKit.
remove(current_hydration_fragment);
set_current_hydration_fragment(null);
remove(hydrate_nodes);
set_hydrating(false);
mismatch = true;
} else {
// Remove the ssr:if comment node or else it will confuse the subsequent hydration algorithm
current_hydration_fragment.shift();
hydrate_nodes.shift();
}

@@ -78,18 +70,3 @@ }

} else {
consequent_effect = render_effect(
() => {
consequent_dom = consequent_fn(anchor);
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (consequent_dom !== undefined) {
remove(consequent_dom);
consequent_dom = undefined;
}
};
},
block,
true
);
consequent_effect = render_effect(() => consequent_fn(anchor), true);
}

@@ -100,3 +77,2 @@

alternate_effect = null;
if (alternate_dom) remove(alternate_dom);
});

@@ -108,18 +84,3 @@ }

} else if (alternate_fn) {
alternate_effect = render_effect(
() => {
alternate_dom = alternate_fn(anchor);
return () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (alternate_dom !== undefined) {
remove(alternate_dom);
alternate_dom = undefined;
}
};
},
block,
true
);
alternate_effect = render_effect(() => alternate_fn(anchor), true);
}

@@ -130,3 +91,2 @@

consequent_effect = null;
if (consequent_dom) remove(consequent_dom);
});

@@ -137,6 +97,6 @@ }

if (mismatch) {
// Set fragment so that Svelte continues to operate in hydration mode
set_current_hydration_fragment([]);
// continue in hydration mode
set_hydrating(true);
}
}, block);
});

@@ -148,12 +108,3 @@ if (elseif) {

if_effect.ondestroy = () => {
// TODO make this unnecessary by linking the dom to the effect,
// and removing automatically on teardown
if (consequent_dom !== undefined) {
remove(consequent_dom);
}
if (alternate_dom !== undefined) {
remove(alternate_dom);
}
// TODO why is this not automatic? this should be children of `if_effect`
if (consequent_effect) {

@@ -160,0 +111,0 @@ destroy_effect(consequent_effect);

@@ -6,3 +6,2 @@ import { UNINITIALIZED } from '../../constants.js';

import { safe_not_equal } from '../../reactivity/equality.js';
import { create_block } from './utils.js';

@@ -13,8 +12,6 @@ /**

* @param {() => V} get_key
* @param {(anchor: Node) => void} render_fn
* @param {(anchor: Node) => import('#client').Dom | void} render_fn
* @returns {void}
*/
export function key_block(anchor, get_key, render_fn) {
const block = create_block();
hydrate_block_anchor(anchor);

@@ -35,45 +32,34 @@

const key_effect = render_effect(
() => {
if (safe_not_equal(key, (key = get_key()))) {
if (effect) {
var e = effect;
pause_effect(e, () => {
effects.delete(e);
});
}
const key_effect = render_effect(() => {
if (safe_not_equal(key, (key = get_key()))) {
if (effect) {
var e = effect;
pause_effect(e, () => {
effects.delete(e);
});
}
effect = render_effect(
() => {
render_fn(anchor);
effect = render_effect(
() => {
const dom = render_fn(anchor);
const dom = block.d;
return () => {
if (dom !== undefined) {
remove(dom);
}
};
},
true,
true
);
return () => {
if (dom !== null) {
remove(dom);
}
};
},
block,
true,
true
);
effects.add(effect);
}
});
// @ts-expect-error TODO tidy up
effect.d = block.d;
effects.add(effect);
}
},
block,
false
);
key_effect.ondestroy = () => {
for (const e of effects) {
// @ts-expect-error TODO tidy up. ondestroy should be totally unnecessary
if (e.d) remove(e.d);
if (e.dom) remove(e.dom);
}
};
}
import { render_effect } from '../../reactivity/effects.js';
import { remove } from '../reconciler.js';
import { untrack } from '../../runtime.js';
import { create_block } from './utils.js';
/**
* @param {() => Function | null | undefined} get_snippet
* @param {Node} node
* @template {(node: import('#client').TemplateNode, ...args: any[]) => import('#client').Dom} SnippetFn
* @param {() => SnippetFn | null | undefined} get_snippet
* @param {import('#client').TemplateNode} node
* @param {(() => any)[]} args

@@ -13,17 +13,20 @@ * @returns {void}

export function snippet(get_snippet, node, ...args) {
const block = create_block();
/** @type {SnippetFn | null | undefined} */
var snippet_fn;
render_effect(() => {
// Only rerender when the snippet function itself changes,
// not when an eagerly-read prop inside the snippet function changes
const snippet = get_snippet();
if (snippet) {
untrack(() => snippet(node, ...args));
if (snippet_fn === (snippet_fn = get_snippet())) return;
if (snippet_fn) {
// Untrack so we only rerender when the snippet function itself changes,
// not when an eagerly-read prop inside the snippet function changes
var dom = untrack(() => /** @type {SnippetFn} */ (snippet_fn)(node, ...args));
}
return () => {
if (block.d !== null) {
remove(block.d);
if (dom !== undefined) {
remove(dom);
}
};
}, block);
});
}
import { hydrate_block_anchor } from '../hydration.js';
import { pause_effect, render_effect } from '../../reactivity/effects.js';
import { remove } from '../reconciler.js';
import { create_block } from './utils.js';
import { current_effect } from '../../runtime.js';

@@ -13,8 +13,6 @@ // TODO this is very similar to `key`, can we deduplicate?

* @param {() => C} get_component
* @param {(component: C) => void} render_fn
* @param {(component: C) => import('#client').Dom | void} render_fn
* @returns {void}
*/
export function component(anchor, get_component, render_fn) {
const block = create_block();
hydrate_block_anchor(anchor);

@@ -35,47 +33,34 @@

const component_effect = render_effect(
() => {
if (component === (component = get_component())) return;
const component_effect = render_effect(() => {
if (component === (component = get_component())) return;
if (effect) {
var e = effect;
pause_effect(e, () => {
effects.delete(e);
});
}
if (effect) {
var e = effect;
pause_effect(e, () => {
effects.delete(e);
});
}
if (component) {
effect = render_effect(
() => {
render_fn(component);
if (component) {
effect = render_effect(() => {
render_fn(component);
const dom = block.d;
// `render_fn` doesn't return anything, and we can't reference `effect`
// yet, so we reference it indirectly as `current_effect`
const dom = /** @type {import('#client').Effect} */ (current_effect).dom;
return () => {
if (dom !== null) {
remove(dom);
}
};
},
block,
true,
true
);
return () => {
if (dom !== null) remove(dom);
};
}, true);
// @ts-expect-error TODO tidy up
effect.d = block.d;
effects.add(effect);
}
});
effects.add(effect);
}
},
block,
false
);
component_effect.ondestroy = () => {
for (const e of effects) {
// @ts-expect-error TODO tidy up. ondestroy should be totally unnecessary
if (e.d) remove(e.d);
if (e.dom) remove(e.dom);
}
};
}
import { namespace_svg } from '../../../../constants.js';
import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../hydration.js';
import { hydrate_nodes, hydrate_block_anchor, hydrating } from '../hydration.js';
import { empty } from '../operations.js';

@@ -13,8 +13,7 @@ import {

import { set_should_intro } from '../../render.js';
import { current_each_item_block, set_current_each_item_block } from './each.js';
import { create_block } from './utils.js';
import { current_block } from '../../runtime.js';
import { current_each_item, set_current_each_item } from './each.js';
import { current_effect } from '../../runtime.js';
/**
* @param {import('#client').Block} block
* @param {import('#client').Effect} effect
* @param {Element} from

@@ -24,4 +23,5 @@ * @param {Element} to

*/
function swap_block_dom(block, from, to) {
const dom = block.d;
function swap_block_dom(effect, from, to) {
const dom = effect.dom;
if (is_array(dom)) {

@@ -35,3 +35,3 @@ for (let i = 0; i < dom.length; i++) {

} else if (dom === from) {
block.d = to;
effect.dom = to;
}

@@ -48,4 +48,3 @@ }

export function element(anchor, get_tag, is_svg, render_fn) {
const parent_block = /** @type {import('#client').Block} */ (current_block);
const block = create_block();
const parent_effect = /** @type {import('#client').Effect} */ (current_effect);

@@ -71,3 +70,3 @@ hydrate_block_anchor(anchor);

*/
let each_item_block = current_each_item_block;
let each_item_block = current_each_item;

@@ -79,4 +78,4 @@ const wrapper = render_effect(() => {

// See explanation of `each_item_block` above
var previous_each_item_block = current_each_item_block;
set_current_each_item_block(each_item_block);
var previous_each_item = current_each_item;
set_current_each_item(each_item_block);

@@ -112,34 +111,33 @@ // We try our best infering the namespace in case it's not possible to determine statically,

if (next_tag && next_tag !== current_tag) {
effect = render_effect(
() => {
const prev_element = element;
element = hydrating
? /** @type {Element} */ (current_hydration_fragment[0])
: ns
? document.createElementNS(ns, next_tag)
: document.createElement(next_tag);
effect = render_effect(() => {
const prev_element = element;
element = hydrating
? /** @type {Element} */ (hydrate_nodes[0])
: ns
? document.createElementNS(ns, next_tag)
: document.createElement(next_tag);
if (render_fn) {
let anchor;
if (hydrating) {
// Use the existing ssr comment as the anchor so that the inner open and close
// methods can pick up the existing nodes correctly
anchor = /** @type {Comment} */ (element.firstChild);
} else {
anchor = empty();
element.appendChild(anchor);
}
render_fn(element, anchor);
if (render_fn) {
// If hydrating, use the existing ssr comment as the anchor so that the
// inner open and close methods can pick up the existing nodes correctly
var child_anchor = hydrating
? /** @type {Comment} */ (element.firstChild)
: element.appendChild(empty());
if (child_anchor) {
// `child_anchor` can be undefined if this is a void element with children,
// i.e. `<svelte:element this={"hr"}>...</svelte:element>`. This is
// user error, but we warn on it elsewhere (in dev) so here we just
// silently ignore it
render_fn(element, child_anchor);
}
}
anchor.before(element);
anchor.before(element);
if (prev_element) {
swap_block_dom(parent_block, prev_element, element);
prev_element.remove();
}
},
block,
true
);
if (prev_element) {
swap_block_dom(parent_effect, prev_element, element);
prev_element.remove();
}
}, true);
}

@@ -151,4 +149,4 @@

set_current_each_item_block(previous_each_item_block);
}, block);
set_current_each_item(previous_each_item);
});

@@ -158,3 +156,2 @@ wrapper.ondestroy = () => {

remove(element);
block.d = null;
element = null;

@@ -161,0 +158,0 @@ }

@@ -1,61 +0,46 @@

import {
current_hydration_fragment,
get_hydration_fragment,
hydrating,
set_current_hydration_fragment
} from '../hydration.js';
import { hydrate_nodes, hydrating, set_hydrate_nodes, update_hydrate_nodes } from '../hydration.js';
import { empty } from '../operations.js';
import { render_effect } from '../../reactivity/effects.js';
import { remove } from '../reconciler.js';
import { create_block } from './utils.js';
/**
* @param {(anchor: Node | null) => void} render_fn
* @param {(anchor: Node | null) => import('#client').Dom | void} render_fn
* @returns {void}
*/
export function head(render_fn) {
const block = create_block();
// The head function may be called after the first hydration pass and ssr comment nodes may still be present,
// therefore we need to skip that when we detect that we're not in hydration mode.
let hydration_fragment = null;
let previous_hydration_fragment = null;
let previous_hydrate_nodes = null;
let was_hydrating = hydrating;
let is_hydrating = hydrating;
if (is_hydrating) {
hydration_fragment = get_hydration_fragment(document.head.firstChild);
previous_hydration_fragment = current_hydration_fragment;
set_current_hydration_fragment(hydration_fragment);
if (hydrating) {
previous_hydrate_nodes = hydrate_nodes;
update_hydrate_nodes(document.head.firstChild);
}
var anchor = document.head.appendChild(empty());
try {
const head_effect = render_effect(
() => {
const current = block.d;
if (current !== null) {
remove(current);
block.d = null;
}
let anchor = null;
if (!hydrating) {
anchor = empty();
document.head.appendChild(anchor);
}
render_fn(anchor);
},
block,
false
);
/** @type {import('#client').Dom | null} */
var dom = null;
const head_effect = render_effect(() => {
if (dom !== null) {
remove(dom);
head_effect.dom = dom = null;
}
dom = render_fn(hydrating ? null : anchor) ?? null;
});
head_effect.ondestroy = () => {
const current = block.d;
if (current !== null) {
remove(current);
if (dom !== null) {
remove(dom);
}
};
} finally {
if (is_hydrating) {
set_current_hydration_fragment(previous_hydration_fragment);
if (was_hydrating) {
set_hydrate_nodes(previous_hydrate_nodes);
}
}
}

@@ -101,3 +101,3 @@ import { createClassComponent } from '../../../../legacy/legacy-client.js';

return (anchor) => {
const node = open(anchor, true, () => {
const node = open(anchor, () => {
const slot = document.createElement('slot');

@@ -104,0 +104,0 @@ if (name !== 'default') {

import { hydrating } from '../hydration.js';
import { render_effect } from '../../reactivity/effects.js';
import { current_block } from '../../runtime.js';

@@ -20,3 +19,2 @@ /**

},
current_block,
true,

@@ -23,0 +21,0 @@ false

@@ -8,3 +8,3 @@ import { noop } from '../../../common.js';

import { is_function } from '../../utils.js';
import { current_each_item_block } from '../blocks/each.js';
import { current_each_item } from '../blocks/each.js';
import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../constants.js';

@@ -81,3 +81,3 @@ import { EFFECT_RAN } from '../../constants.js';

export function animation(element, get_fn, get_params) {
var block = /** @type {import('#client').EachItem} */ (current_each_item_block);
var item = /** @type {import('#client').EachItem} */ (current_each_item);

@@ -93,3 +93,3 @@ /** @type {DOMRect} */

block.a ??= {
item.a ??= {
element,

@@ -124,3 +124,3 @@ measure() {

// moment as a reconciliation
block.a.element = element;
item.a.element = element;
}

@@ -127,0 +127,0 @@

@@ -1,3 +0,1 @@

// Handle hydration
import { schedule_task } from './task.js';

@@ -12,2 +10,7 @@ import { empty } from './operations.js';

/** @param {boolean} value */
export function set_hydrating(value) {
hydrating = value;
}
/**

@@ -17,58 +20,75 @@ * Array of nodes to traverse for hydration. This will be null if we're not hydrating, but for

* the `hydrating` flag to tell whether or not we're in hydration mode at which point this is set.
* @type {import('../types.js').TemplateNode[]}
* @type {import('#client').TemplateNode[]}
*/
export let current_hydration_fragment = /** @type {any} */ (null);
export let hydrate_nodes = /** @type {any} */ (null);
/**
* @param {null | import('../types.js').TemplateNode[]} fragment
* @param {null | import('#client').TemplateNode[]} nodes
* @returns {void}
*/
export function set_current_hydration_fragment(fragment) {
hydrating = fragment !== null;
current_hydration_fragment = /** @type {import('../types.js').TemplateNode[]} */ (fragment);
export function set_hydrate_nodes(nodes) {
hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes);
}
/**
* Returns all nodes between the first `<!--ssr:...-->` comment tag pair encountered.
* @param {Node | null} first
* @param {boolean} [insert_text] Whether to insert an empty text node if `nodes` is empty
*/
export function update_hydrate_nodes(first, insert_text) {
const nodes = get_hydrate_nodes(first, insert_text);
set_hydrate_nodes(nodes);
return nodes;
}
/**
* Returns all nodes between the first `<![>...<!]>` comment tag pair encountered.
* @param {Node | null} node
* @param {boolean} [insert_text] Whether to insert an empty text node if the fragment is empty
* @returns {import('../types.js').TemplateNode[] | null}
* @param {boolean} [insert_text] Whether to insert an empty text node if `nodes` is empty
* @returns {import('#client').TemplateNode[] | null}
*/
export function get_hydration_fragment(node, insert_text = false) {
/** @type {import('../types.js').TemplateNode[]} */
const fragment = [];
function get_hydrate_nodes(node, insert_text = false) {
/** @type {import('#client').TemplateNode[]} */
var nodes = [];
/** @type {null | Node} */
let current_node = node;
var current_node = /** @type {null | import('#client').TemplateNode} */ (node);
/** @type {null | string} */
let target_depth = null;
var depth = 0;
var will_start = false;
var started = false;
while (current_node !== null) {
const node_type = current_node.nodeType;
const next_sibling = current_node.nextSibling;
if (node_type === 8) {
const data = /** @type {Comment} */ (current_node).data;
if (data.startsWith('ssr:')) {
const depth = data.slice(4);
if (target_depth === null) {
target_depth = depth;
} else if (depth === target_depth) {
if (insert_text && fragment.length === 0) {
const text = empty();
fragment.push(text);
/** @type {Node} */ (current_node.parentNode).insertBefore(text, current_node);
if (current_node.nodeType === 8) {
var data = /** @type {Comment} */ (current_node).data;
if (data === '[') {
depth += 1;
will_start = true;
} else if (data === ']') {
if (!started) {
// TODO get rid of this — it exists because each blocks are doubly wrapped
return null;
}
if (--depth === 0) {
if (insert_text && nodes.length === 0) {
var text = empty();
nodes.push(text);
current_node.before(text);
}
return fragment;
} else {
fragment.push(/** @type {Text | Comment | Element} */ (current_node));
return nodes;
}
current_node = next_sibling;
continue;
}
}
if (target_depth !== null) {
fragment.push(/** @type {Text | Comment | Element} */ (current_node));
if (started) {
nodes.push(current_node);
}
current_node = next_sibling;
current_node = /** @type {null | import('#client').TemplateNode} */ (current_node.nextSibling);
started = will_start;
}
return null;

@@ -84,18 +104,30 @@ }

if (node.nodeType === 8) {
// @ts-ignore
var nodes = node.$$fragment ?? get_hydrate_nodes(node);
set_hydrate_nodes(nodes);
}
/**
* Expects to only be called in hydration mode
* @param {Node} node
* @returns {Node}
*/
export function capture_fragment_from_node(node) {
if (
node.nodeType === 8 &&
/** @type {Comment} */ (node).data === '[' &&
hydrate_nodes[hydrate_nodes.length - 1] !== node
) {
const nodes = /** @type {Node[]} */ (get_hydrate_nodes(node));
const last_child = nodes[nodes.length - 1] || node;
const target = /** @type {Node} */ (last_child.nextSibling);
// @ts-ignore
let fragment = node.$$fragment;
if (fragment === undefined) {
fragment = get_hydration_fragment(node);
} else {
schedule_task(() => {
// @ts-expect-error clean up memory
node.$$fragment = undefined;
});
}
set_current_hydration_fragment(fragment);
} else {
const first_child = /** @type {Element | null} */ (node.firstChild);
set_current_hydration_fragment(first_child === null ? [] : [first_child]);
target.$$fragment = nodes;
schedule_task(() => {
// @ts-expect-error clean up memory
target.$$fragment = undefined;
});
return target;
}
return node;
}

@@ -1,2 +0,2 @@

import { current_hydration_fragment, get_hydration_fragment, hydrating } from './hydration.js';
import { capture_fragment_from_node, hydrate_nodes, hydrating } from './hydration.js';
import { get_descriptor } from '../utils.js';

@@ -126,18 +126,14 @@

const child = first_child_get.call(node);
if (hydrating) {
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty
if (child === null) {
const text = empty();
node.appendChild(text);
return text;
} else {
return capture_fragment_from_node(child);
}
if (!hydrating) return child;
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty
if (child === null) {
return node.appendChild(empty());
}
return child;
return capture_fragment_from_node(child);
}
/**
* @template {Node | Node[]} N
* @param {N} node
* @param {DocumentFragment | import('#client').TemplateNode[]} fragment
* @param {boolean} is_text

@@ -147,25 +143,25 @@ * @returns {Node | null}

/*#__NO_SIDE_EFFECTS__*/
export function child_frag(node, is_text) {
if (hydrating) {
const first_node = /** @type {Node[]} */ (node)[0];
export function first_child(fragment, is_text) {
if (!hydrating) {
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
return first_child_get.call(/** @type {DocumentFragment} */ (fragment));
}
// if an {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one
if (is_text && first_node?.nodeType !== 3) {
const text = empty();
current_hydration_fragment.unshift(text);
if (first_node) {
/** @type {DocumentFragment} */ (first_node.parentNode).insertBefore(text, first_node);
}
return text;
}
// when we _are_ hydrating, `fragment` is an array of nodes
const first_node = /** @type {import('#client').TemplateNode[]} */ (fragment)[0];
if (first_node !== null) {
return capture_fragment_from_node(first_node);
}
// if an {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one
if (is_text && first_node?.nodeType !== 3) {
const text = empty();
hydrate_nodes.unshift(text);
first_node?.before(text);
return text;
}
return first_node;
if (first_node !== null) {
return capture_fragment_from_node(first_node);
}
return first_child_get.call(/** @type {Node} */ (node));
return first_node;
}

@@ -182,2 +178,3 @@

const next_sibling = next_sibling_get.call(node);
if (hydrating) {

@@ -189,9 +186,7 @@ // if a sibling {expression} is empty during SSR, there might be no

if (next_sibling) {
const index = current_hydration_fragment.indexOf(
/** @type {Text | Comment | Element} */ (next_sibling)
);
current_hydration_fragment.splice(index, 0, text);
/** @type {DocumentFragment} */ (next_sibling.parentNode).insertBefore(text, next_sibling);
const index = hydrate_nodes.indexOf(/** @type {Text | Comment | Element} */ (next_sibling));
hydrate_nodes.splice(index, 0, text);
next_sibling.before(text);
} else {
current_hydration_fragment.push(text);
hydrate_nodes.push(text);
}

@@ -206,2 +201,3 @@

}
return next_sibling;

@@ -234,22 +230,1 @@ }

}
/**
* Expects to only be called in hydration mode
* @param {Node} node
* @returns {Node}
*/
function capture_fragment_from_node(node) {
if (
node.nodeType === 8 &&
/** @type {Comment} */ (node).data.startsWith('ssr:') &&
current_hydration_fragment[current_hydration_fragment.length - 1] !== node
) {
const fragment = /** @type {Array<Element | Text | Comment>} */ (get_hydration_fragment(node));
const last_child = fragment[fragment.length - 1] || node;
const target = /** @type {Node} */ (last_child.nextSibling);
// @ts-ignore
target.$$fragment = fragment;
return target;
}
return node;
}
import { append_child } from './operations.js';
import { current_hydration_fragment, hydrate_block_anchor, hydrating } from './hydration.js';
import { hydrate_nodes, hydrate_block_anchor, hydrating } from './hydration.js';
import { is_array } from '../utils.js';

@@ -79,3 +79,3 @@

if (hydrating) {
return current_hydration_fragment;
return hydrate_nodes;
}

@@ -97,3 +97,3 @@ var html = value + '';

var clone = content.cloneNode(true);
frag_nodes = Array.from(clone.childNodes);
frag_nodes = [...clone.childNodes];
frag_nodes.forEach((node) => {

@@ -100,0 +100,0 @@ target.before(node);

@@ -1,2 +0,2 @@

import { current_hydration_fragment, hydrate_block_anchor, hydrating } from './hydration.js';
import { hydrate_nodes, hydrate_block_anchor, hydrating } from './hydration.js';
import { child, clone_node, empty } from './operations.js';

@@ -8,3 +8,3 @@ import {

} from './reconciler.js';
import { current_block } from '../runtime.js';
import { current_effect } from '../runtime.js';
import { is_array } from '../utils.js';

@@ -91,14 +91,13 @@

*/
/*#__NO_SIDE_EFFECTS__*/
function open_template(is_fragment, use_clone_node, anchor, template_element_fn) {
if (hydrating) {
if (anchor !== null) {
// TODO why is this sometimes null and sometimes not? needs clear documentation
hydrate_block_anchor(anchor);
}
// In ssr+hydration optimization mode, we might remove the template_element,
// so we need to is_fragment flag to properly handle hydrated content accordingly.
const fragment = current_hydration_fragment;
if (fragment !== null) {
return is_fragment ? fragment : /** @type {Element} */ (fragment[0]);
}
return is_fragment ? hydrate_nodes : /** @type {Element} */ (hydrate_nodes[0]);
}
return use_clone_node

@@ -111,9 +110,8 @@ ? clone_node(/** @type {() => Element} */ (template_element_fn)(), true)

* @param {null | Text | Comment | Element} anchor
* @param {boolean} use_clone_node
* @param {() => Node} [template_element_fn]
* @returns {Element | DocumentFragment | Node[]}
* @param {() => Node} template_element_fn
* @param {boolean} [use_clone_node]
* @returns {Element}
*/
/*#__NO_SIDE_EFFECTS__*/
export function open(anchor, use_clone_node, template_element_fn) {
return open_template(false, use_clone_node, anchor, template_element_fn);
export function open(anchor, template_element_fn, use_clone_node = true) {
return /** @type {Element} */ (open_template(false, use_clone_node, anchor, template_element_fn));
}

@@ -123,8 +121,7 @@

* @param {null | Text | Comment | Element} anchor
* @param {boolean} use_clone_node
* @param {() => Node} [template_element_fn]
* @param {() => Node} template_element_fn
* @param {boolean} [use_clone_node]
* @returns {Element | DocumentFragment | Node[]}
*/
/*#__NO_SIDE_EFFECTS__*/
export function open_frag(anchor, use_clone_node, template_element_fn) {
export function open_frag(anchor, template_element_fn, use_clone_node = true) {
return open_template(true, use_clone_node, anchor, template_element_fn);

@@ -142,3 +139,3 @@ }

/** @type {Node | null} */
var node = /** @type {any} */ (open(anchor, true, space_template));
var node = /** @type {any} */ (open(anchor, space_template));
// if an {expression} is empty during SSR, there might be no

@@ -177,3 +174,3 @@ // text node to hydrate (or an anchor comment is falsely detected instead)

export function comment(anchor) {
return open_frag(anchor, true, comment_template);
return open_frag(anchor, comment_template);
}

@@ -184,3 +181,3 @@

* and insert the elements into the dom (in client mode).
* @param {Element | Text} dom
* @param {import('#client').Dom} dom
* @param {boolean} is_fragment

@@ -191,14 +188,18 @@ * @param {null | Text | Comment | Element} anchor

function close_template(dom, is_fragment, anchor) {
/** @type {import('#client').Dom} */
var current = is_fragment
? is_array(dom)
? dom
: /** @type {import('#client').TemplateNode[]} */ (Array.from(dom.childNodes))
: dom;
var current = dom;
if (!hydrating && anchor !== null) {
insert(current, anchor);
if (!hydrating) {
if (is_fragment) {
// if hydrating, `dom` is already an array of nodes, but if not then
// we need to create an array to store it on the current effect
current = /** @type {import('#client').Dom} */ ([.../** @type {Node} */ (dom).childNodes]);
}
if (anchor !== null) {
// TODO as with `open_template — why is this sometimes null and sometimes not?
insert(current, anchor);
}
}
/** @type {import('#client').Block} */ (current_block).d = current;
/** @type {import('#client').Effect} */ (current_effect).dom = current;

@@ -205,0 +206,0 @@ return current;

import { DEV } from 'esm-env';
import {
check_dirtiness,
current_block,
current_component_context,

@@ -28,2 +27,3 @@ current_effect,

import { noop } from '../../common.js';
import { remove } from '../dom/reconciler.js';

@@ -34,11 +34,10 @@ /**

* @param {boolean} sync
* @param {null | import('#client').Block} block
* @param {boolean} init
* @returns {import('#client').Effect}
*/
function create_effect(type, fn, sync, block = current_block, init = true) {
function create_effect(type, fn, sync, init = true) {
/** @type {import('#client').Effect} */
const signal = {
parent: current_effect,
block,
dom: null,
deps: null,

@@ -104,3 +103,3 @@ f: type | DIRTY,

const effect = create_effect(EFFECT, fn, false, current_block, !defer);
const effect = create_effect(EFFECT, fn, false, !defer);

@@ -121,3 +120,3 @@ if (defer) {

export function user_root_effect(fn) {
const effect = render_effect(fn, current_block, true);
const effect = render_effect(fn, true);
return () => {

@@ -223,13 +222,11 @@ destroy_effect(effect);

* @param {(() => void)} fn
* @param {any} block
* @param {any} managed
* @param {any} sync
* @param {boolean} managed
* @param {boolean} sync
* @returns {import('#client').Effect}
*/
export function render_effect(fn, block = current_block, managed = false, sync = true) {
export function render_effect(fn, managed = false, sync = true) {
let flags = RENDER_EFFECT;
if (managed) {
flags |= MANAGED;
}
return create_effect(flags, /** @type {any} */ (fn), sync, block);
if (managed) flags |= MANAGED;
return create_effect(flags, /** @type {any} */ (fn), sync);
}

@@ -253,2 +250,7 @@

effect.teardown?.();
if (effect.dom !== null) {
remove(effect.dom);
}
effect.ondestroy?.();

@@ -262,3 +264,3 @@

effect.ctx =
effect.block =
effect.dom =
effect.deps =

@@ -279,22 +281,47 @@ null;

/** @type {import('#client').TransitionManager[]} */
const transitions = [];
var transitions = [];
pause_children(effect, transitions, true);
let remaining = transitions.length;
out(transitions, () => {
destroy_effect(effect);
callback();
});
}
/**
* Pause multiple effects simultaneously, and coordinate their
* subsequent destruction. Used in each blocks
* @param {import('#client').Effect[]} effects
* @param {() => void} callback
*/
export function pause_effects(effects, callback = noop) {
/** @type {import('#client').TransitionManager[]} */
var transitions = [];
for (var effect of effects) {
pause_children(effect, transitions, true);
}
out(transitions, () => {
for (var effect of effects) {
destroy_effect(effect);
}
callback();
});
}
/**
* @param {import('#client').TransitionManager[]} transitions
* @param {() => void} fn
*/
function out(transitions, fn) {
var remaining = transitions.length;
if (remaining > 0) {
const check = () => {
if (!--remaining) {
destroy_effect(effect);
callback();
}
};
for (const transition of transitions) {
var check = () => --remaining || fn();
for (var transition of transitions) {
transition.out(check);
}
} else {
destroy_effect(effect);
callback();
fn();
}

@@ -301,0 +328,0 @@ }

@@ -1,2 +0,2 @@

import type { Block, ComponentContext, Equals, TransitionManager } from '#client';
import type { Block, ComponentContext, Dom, Equals, TransitionManager } from '#client';
import type { EFFECT, PRE_EFFECT, RENDER_EFFECT } from '../constants';

@@ -40,4 +40,3 @@

parent: Effect | null;
/** The block associated with this effect */
block: null | Block;
dom: Dom | null;
/** The associated component context */

@@ -44,0 +43,0 @@ ctx: null | ComponentContext;

import { DEV } from 'esm-env';
import { append_child, create_element, empty, init_operations } from './dom/operations.js';
import {
append_child,
clear_text_content,
create_element,
empty,
init_operations
} from './dom/operations.js';
import { PassiveDelegatedEvents } from '../../constants.js';

@@ -8,7 +14,8 @@ import { remove } from './dom/reconciler.js';

import {
current_hydration_fragment,
get_hydration_fragment,
hydrate_nodes,
hydrate_block_anchor,
hydrating,
set_current_hydration_fragment
set_hydrate_nodes,
set_hydrating,
update_hydrate_nodes
} from './dom/hydration.js';

@@ -108,3 +115,3 @@ import { array_from } from './utils.js';

* @param {{
* target: Node;
* target: Document | Element | ShadowRoot;
* props?: Props;

@@ -118,5 +125,3 @@ * events?: { [Property in keyof Events]: (e: Events[Property]) => any };

export function mount(component, options) {
init_operations();
const anchor = empty();
options.target.appendChild(anchor);
const anchor = options.target.appendChild(empty());
// Don't flush previous effects to ensure order of outer effects stays consistent

@@ -134,3 +139,3 @@ return flush_sync(() => _mount(component, { ...options, anchor }), false);

* @param {{
* target: Node;
* target: Document | Element | ShadowRoot;
* props?: Props;

@@ -145,32 +150,27 @@ * events?: { [Property in keyof Events]: (e: Events[Property]) => any };

export function hydrate(component, options) {
init_operations();
const container = options.target;
const first_child = /** @type {ChildNode} */ (container.firstChild);
const previous_hydrate_nodes = hydrate_nodes;
// Call with insert_text == true to prevent empty {expressions} resulting in an empty
// fragment array, resulting in a hydration error down the line
const hydration_fragment = get_hydration_fragment(first_child, true);
const previous_hydration_fragment = current_hydration_fragment;
set_current_hydration_fragment(hydration_fragment);
// `nodes` array, resulting in a hydration error down the line
// TODO is both this and the `container.appendChild(anchor)` below necessary?
const nodes = update_hydrate_nodes(first_child, true);
set_hydrating(true);
/** @type {null | Text} */
let anchor = null;
if (hydration_fragment === null) {
anchor = empty();
container.appendChild(anchor);
}
let hydrated = false;
let finished_hydrating = false;
try {
// Don't flush previous effects to ensure order of outer effects stays consistent
return flush_sync(() => {
const anchor = nodes === null ? container.appendChild(empty()) : null;
const instance = _mount(component, { ...options, anchor });
// flush_sync will run this callback and then synchronously run any pending effects,
// which don't belong to the hydration phase anymore - therefore reset it here
set_current_hydration_fragment(null);
finished_hydrating = true;
set_hydrating(false);
hydrated = true;
return instance;
}, false);
} catch (error) {
if (!finished_hydrating && options.recover !== false && hydration_fragment !== null) {
if (!hydrated && options.recover !== false && nodes !== null) {
// eslint-disable-next-line no-console

@@ -184,6 +184,6 @@ console.error(

);
remove(hydration_fragment);
first_child.remove();
hydration_fragment[hydration_fragment.length - 1]?.nextSibling?.remove();
set_current_hydration_fragment(null);
clear_text_content(container);
set_hydrating(false);
return mount(component, options);

@@ -194,3 +194,4 @@ } else {

} finally {
set_current_hydration_fragment(previous_hydration_fragment);
set_hydrating(!!previous_hydrate_nodes);
set_hydrate_nodes(previous_hydrate_nodes);
}

@@ -205,3 +206,3 @@ }

* @param {{
* target: Node;
* target: Document | Element | ShadowRoot;
* anchor: null | Text;

@@ -217,2 +218,4 @@ * props?: Props;

function _mount(Component, options) {
init_operations();
const registered_events = new Set();

@@ -223,8 +226,2 @@ const container = options.target;

/** @type {import('#client').Block} */
const block = {
// dom
d: null
};
/** @type {Exports} */

@@ -234,26 +231,22 @@ // @ts-expect-error will be defined because the render effect runs synchronously

const effect = render_effect(
() => {
if (options.context) {
push({});
/** @type {import('../client/types.js').ComponentContext} */ (current_component_context).c =
options.context;
}
if (!options.props) {
options.props = /** @type {Props} */ ({});
}
if (options.events) {
// We can't spread the object or else we'd lose the state proxy stuff, if it is one
/** @type {any} */ (options.props).$$events = options.events;
}
component =
// @ts-expect-error the public typings are not what the actual function looks like
Component(options.anchor, options.props) || {};
if (options.context) {
pop();
}
},
block,
true
);
const effect = render_effect(() => {
if (options.context) {
push({});
/** @type {import('../client/types.js').ComponentContext} */ (current_component_context).c =
options.context;
}
if (!options.props) {
options.props = /** @type {Props} */ ({});
}
if (options.events) {
// We can't spread the object or else we'd lose the state proxy stuff, if it is one
/** @type {any} */ (options.props).$$events = options.events;
}
component =
// @ts-expect-error the public typings are not what the actual function looks like
Component(options.anchor, options.props) || {};
if (options.context) {
pop();
}
}, true);

@@ -305,3 +298,3 @@ const bound_event_listener = handle_event_propagation.bind(null, container);

root_event_handles.delete(event_handle);
const dom = block.d;
const dom = effect.dom;
if (dom !== null) {

@@ -308,0 +301,0 @@ remove(dom);

@@ -110,7 +110,3 @@ import { DEV } from 'esm-env';

// Handle rendering tree blocks and anchors
/** @type {null | import('./types.js').Block} */
export let current_block = null;
// Handling runtime component context
/** @type {import('./types.js').ComponentContext | null} */

@@ -391,3 +387,2 @@ export let current_component_context = null;

const previous_component_context = current_component_context;
const previous_block = current_block;

@@ -398,3 +393,2 @@ const component_context = signal.ctx;

current_component_context = component_context;
current_block = signal.block;

@@ -409,3 +403,2 @@ try {

current_component_context = previous_component_context;
current_block = previous_block;
}

@@ -521,3 +514,2 @@

const target_level = signal.l;
const target_block = signal.block;
const is_pre_effect = (flags & PRE_EFFECT) !== 0;

@@ -538,3 +530,3 @@ let target_signal;

target_signal_level < target_level ||
target_signal.block !== target_block ||
target_signal !== signal ||
(is_target_pre_effect && !is_pre_effect)

@@ -541,0 +533,0 @@ ) {

@@ -54,6 +54,3 @@ import { STATE_SYMBOL } from './constants.js';

export interface Block {
/** dom */
d: null | Dom;
}
export interface Block {}

@@ -70,4 +67,2 @@ export type EachState = {

a: AnimationManager | null;
/** dom */
d: null | Dom;
/** effect */

@@ -74,0 +69,0 @@ e: Effect;

@@ -67,3 +67,3 @@ export {

child,
child_frag,
first_child,
sibling,

@@ -70,0 +70,0 @@ $window as window,

@@ -165,9 +165,8 @@ import * as $ from '../client/runtime.js';

if (!VoidElements.has(tag)) {
const anchor = tag !== 'textarea' ? create_anchor(payload) : null;
if (anchor !== null) {
payload.out += anchor;
if (tag !== 'textarea') {
payload.out += '<![>';
}
children_fn();
if (anchor !== null) {
payload.out += anchor;
if (tag !== 'textarea') {
payload.out += '<!]>';
}

@@ -191,8 +190,6 @@ payload.out += `</${tag}>`;

const payload = create_payload();
const root_anchor = create_anchor(payload);
const root_head_anchor = create_anchor(payload.head);
const prev_on_destroy = on_destroy;
on_destroy = [];
payload.out += root_anchor;
payload.out += '<![>';

@@ -208,3 +205,3 @@ if (options.context) {

}
payload.out += root_anchor;
payload.out += '<!]>';
for (const cleanup of on_destroy) cleanup();

@@ -216,3 +213,3 @@ on_destroy = prev_on_destroy;

payload.head.out || payload.head.title
? payload.head.title + root_head_anchor + payload.head.out + root_head_anchor
? payload.head.title + '<![>' + payload.head.out + '<!]>'
: '',

@@ -291,13 +288,12 @@ html: payload.out

const styles = style_object_to_string(props);
const anchor = create_anchor(payload);
if (is_html) {
payload.out += `<div style="display: contents; ${styles}">${anchor}`;
payload.out += `<div style="display: contents; ${styles}"><![>`;
} else {
payload.out += `<g style="${styles}">${anchor}`;
payload.out += `<g style="${styles}"><![>`;
}
component();
if (is_html) {
payload.out += `${anchor}</div>`;
payload.out += `<!]></div>`;
} else {
payload.out += `${anchor}</g>`;
payload.out += `<!]></g>`;
}

@@ -642,14 +638,2 @@ }

/** @param {{ anchor: number }} payload */
export function create_anchor(payload) {
const depth = payload.anchor++;
return `<!--ssr:${depth}-->`;
}
/** @returns {[() => false, (value: boolean) => void]} */
export function selector() {
// Add SSR stubs
return [() => false, noop];
}
/**

@@ -656,0 +640,0 @@ * @param {number} timeout

@@ -9,3 +9,3 @@ // generated during release, do not modify

*/
export const VERSION = '5.0.0-next.82';
export const VERSION = '5.0.0-next.83';
export const PUBLIC_VERSION = '5';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc