Socket
Socket
Sign inDemoInstall

svelte

Package Overview
Dependencies
18
Maintainers
3
Versions
596
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.0-next.96 to 5.0.0-next.97

src/internal/client/dev/hmr.js

2

package.json

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

"license": "MIT",
"version": "5.0.0-next.96",
"version": "5.0.0-next.97",
"type": "module",

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

@@ -418,11 +418,27 @@ import { walk } from 'zimmerframe';

...module.body,
b.export_default(
b.function_declaration(
b.id(analysis.name),
[b.id('$$anchor'), b.id('$$props')],
component_block
)
b.function_declaration(
b.id(analysis.name),
[b.id('$$anchor'), b.id('$$props')],
component_block
)
];
if (options.hmr) {
body.push(
b.export_default(
b.conditional(
b.import_meta_hot(),
b.call('$.hmr', b.member(b.import_meta_hot(), b.id('data')), b.id(analysis.name)),
b.id(analysis.name)
)
),
b.if(
b.import_meta_hot(),
b.stmt(b.call('import.meta.hot.acceptExports', b.literal('default')))
)
);
} else {
body.push(b.export_default(b.id(analysis.name)));
}
if (options.dev) {

@@ -429,0 +445,0 @@ if (options.filename) {

@@ -181,2 +181,8 @@ import type {

cssOutputFilename?: string;
/**
* If `true`, compiles components with hot reloading support.
*
* @default false
*/
hmr?: boolean;
}

@@ -229,2 +235,3 @@

customElementOptions: SvelteOptions['customElement'];
hmr: CompileOptions['hmr'];
};

@@ -231,0 +238,0 @@

@@ -603,2 +603,16 @@ import { regex_is_valid_identifier } from '../phases/patterns.js';

/**
* @return {import('estree').MemberExpression}
*/
export function import_meta_hot() {
return member(
{
type: 'MetaProperty',
meta: id('import'),
property: id('meta')
},
id('hot')
);
}
export {

@@ -605,0 +619,0 @@ await_builder as await,

@@ -98,2 +98,4 @@ import { error } from './errors.js';

hmr: boolean(false),
sourcemap: validator(undefined, (input) => {

@@ -100,0 +102,0 @@ // Source maps can take on a variety of values, including string, JSON, map objects from magic-string and source-map,

@@ -29,5 +29,2 @@ import {

var NEW_ITEM = -1;
var LIS_ITEM = -2;
/**

@@ -46,15 +43,23 @@ * The row of a keyed each block that is currently updating. We track this

/**
* @param {any} _
* @param {number} i
*/
export function index(_, i) {
return i;
}
/**
* Pause multiple effects simultaneously, and coordinate their
* subsequent destruction. Used in each blocks
* @param {import('#client').Effect[]} effects
* @param {import('#client').EachItem[]} items
* @param {null | Node} controlled_anchor
* @param {() => void} [callback]
*/
function pause_effects(effects, controlled_anchor, callback) {
function pause_effects(items, controlled_anchor, callback) {
/** @type {import('#client').TransitionManager[]} */
var transitions = [];
var length = effects.length;
var length = items.length;
for (var i = 0; i < length; i++) {
pause_children(effects[i], transitions, true);
pause_children(items[i].e, transitions, true);
}

@@ -64,3 +69,3 @@

// DOM element, so we can apply a fast-path for clearing the contents of the element.
if (effects.length > 0 && transitions.length === 0 && controlled_anchor !== null) {
if (length > 0 && transitions.length === 0 && controlled_anchor !== null) {
var parent_node = /** @type {Element} */ (controlled_anchor.parentNode);

@@ -73,3 +78,3 @@ parent_node.textContent = '';

for (var i = 0; i < length; i++) {
destroy_effect(effects[i]);
destroy_effect(items[i].e);
}

@@ -86,11 +91,10 @@

* @param {() => V[]} get_collection
* @param {null | ((item: V) => string)} get_key
* @param {(value: V, index: number) => any} get_key
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn
* @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn
* @returns {void}
*/
function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn, reconcile_fn) {
export function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn = null) {
/** @type {import('#client').EachState} */
var state = { flags, items: [] };
var state = { flags, items: new Map(), next: null };

@@ -121,4 +125,2 @@ var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;

var keys = get_key === null ? array : array.map(get_key);
var length = array.length;

@@ -154,7 +156,11 @@

if (hydrating) {
var b_items = [];
/** @type {Node} */
var child_anchor = hydrate_nodes[0];
/** @type {import('#client').EachItem | import('#client').EachState} */
var prev = state;
/** @type {import('#client').EachItem} */
var item;
for (var i = 0; i < length; i++) {

@@ -173,4 +179,9 @@ if (

child_anchor = hydrate_anchor(child_anchor);
b_items[i] = create_item(child_anchor, array[i], keys?.[i], i, render_fn, flags);
var value = array[i];
var key = get_key(value, i);
item = create_item(child_anchor, prev, null, value, key, i, render_fn, flags);
state.items.set(key, item);
child_anchor = /** @type {Comment} */ (child_anchor.nextSibling);
prev = item;
}

@@ -186,8 +197,6 @@

}
state.items = b_items;
}
if (!hydrating) {
reconcile_fn(array, state, anchor, render_fn, flags, keys);
reconcile(array, state, anchor, render_fn, flags, get_key);
}

@@ -218,29 +227,2 @@

* @template V
* @param {Element | Comment} anchor
* @param {number} flags
* @param {() => V[]} get_collection
* @param {null | ((item: V) => string)} get_key
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} [fallback_fn]
* @returns {void}
*/
export function each_keyed(anchor, flags, get_collection, get_key, render_fn, fallback_fn = null) {
each(anchor, flags, get_collection, get_key, render_fn, fallback_fn, reconcile_tracked_array);
}
/**
* @template V
* @param {Element | Comment} anchor
* @param {number} flags
* @param {() => V[]} get_collection
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} [fallback_fn]
* @returns {void}
*/
export function each_indexed(anchor, flags, get_collection, render_fn, fallback_fn = null) {
each(anchor, flags, get_collection, null, render_fn, fallback_fn, reconcile_indexed_array);
}
/**
* @template V
* @param {Array<V>} array

@@ -251,305 +233,179 @@ * @param {import('#client').EachState} state

* @param {number} flags
* @param {(value: V, index: number) => any} get_key
* @returns {void}
*/
function reconcile_indexed_array(array, state, anchor, render_fn, flags) {
var a_items = state.items;
function reconcile(array, state, anchor, render_fn, flags, get_key) {
var is_animated = (flags & EACH_IS_ANIMATED) !== 0;
var should_update = (flags & (EACH_ITEM_REACTIVE | EACH_INDEX_REACTIVE)) !== 0;
var a = a_items.length;
var b = array.length;
var min = Math.min(a, b);
var length = array.length;
var items = state.items;
var first = state.next;
var current = first;
/** @type {typeof a_items} */
var b_items = Array(b);
/** @type {Set<import('#client').EachItem>} */
var seen = new Set();
var item;
var value;
/** @type {import('#client').EachState | import('#client').EachItem} */
var prev = state;
// update items
for (var i = 0; i < min; i += 1) {
value = array[i];
item = a_items[i];
b_items[i] = item;
update_item(item, value, i, flags);
resume_effect(item.e);
}
/** @type {import('#client').EachItem[]} */
var to_animate = [];
if (b > a) {
// add items
for (; i < b; i += 1) {
value = array[i];
item = create_item(anchor, value, null, i, render_fn, flags);
b_items[i] = item;
}
/** @type {import('#client').EachItem[]} */
var matched = [];
state.items = b_items;
} else if (a > b) {
// remove items
var effects = [];
for (i = b; i < a; i += 1) {
effects.push(a_items[i].e);
}
/** @type {import('#client').EachItem[]} */
var stashed = [];
var controlled_anchor = (flags & EACH_IS_CONTROLLED) !== 0 && b === 0 ? anchor : null;
/** @type {V} */
var value;
pause_effects(effects, controlled_anchor, () => {
state.items.length = b;
});
}
}
/** @type {any} */
var key;
/**
* Reconcile arrays by the equality of the elements in the array. This algorithm
* is based on Ivi's reconcilation logic:
* https://github.com/localvoid/ivi/blob/9f1bd0918f487da5b131941228604763c5d8ef56/packages/ivi/src/client/core.ts#L968
* @template V
* @param {Array<V>} array
* @param {import('#client').EachState} state
* @param {Element | Comment | Text} anchor
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: number | import('#client').Source<number>) => void} render_fn
* @param {number} flags
* @param {any[]} keys
* @returns {void}
*/
function reconcile_tracked_array(array, state, anchor, render_fn, flags, keys) {
var a_items = state.items;
var a = a_items.length;
var b = array.length;
/** @type {Array<import('#client').EachItem>} */
var b_items = Array(b);
var is_animated = (flags & EACH_IS_ANIMATED) !== 0;
var should_update = (flags & (EACH_ITEM_REACTIVE | EACH_INDEX_REACTIVE)) !== 0;
var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
var start = 0;
/** @type {import('#client').EachItem | undefined} */
var item;
/** @type {import('#client').Effect[]} */
var to_destroy = [];
/** @type {Array<import('#client').EachItem>} */
var to_animate = [];
/** @type {number} */
var i;
// Step 1 — trim common suffix
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);
if (is_animated) {
for (i = 0; i < length; i += 1) {
value = array[i];
key = get_key(value, i);
item = items.get(key);
resume_effect(item.e);
if (should_update) {
update_item(item, array[b], b, flags);
if (item !== undefined) {
item.a?.measure();
to_animate.push(item);
}
}
if (is_animated) {
item.a?.measure();
to_animate.push(item);
}
}
// Step 2 — trim common prefix
while (start < a && start < b && a_items[start].k === keys[start]) {
item = b_items[start] = a_items[start];
for (i = 0; i < length; i += 1) {
value = array[i];
key = get_key(value, i);
item = items.get(key);
resume_effect(item.e);
if (item === undefined) {
prev = create_item(
current ? get_first_child(current) : anchor,
prev,
prev.next,
value,
key,
i,
render_fn,
flags
);
if (should_update) {
update_item(item, array[start], start, flags);
}
if (is_animated) {
item.a?.measure();
to_animate.push(item);
}
items.set(key, prev);
start += 1;
}
matched = [];
stashed = [];
// Step 3 — update
if (start === a) {
// add only
while (start < b) {
item = create_item(anchor, array[start], keys[start], start, render_fn, flags);
b_items[start++] = item;
current = prev.next;
continue;
}
} else if (start === b) {
// remove only
while (start < a) {
to_destroy.push(a_items[start++].e);
}
} else {
// reconcile
var moved = false;
var sources = new Int32Array(b - start);
var indexes = new Map();
var i;
var index;
var last_item;
// store the indexes of each item in the new world
for (i = start; i < b; i += 1) {
sources[i - start] = NEW_ITEM;
map_set(indexes, keys[i], i);
if (should_update) {
update_item(item, value, i, flags);
}
if (is_animated) {
// 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_items.length; i += 1) {
item = a_items[i];
if (indexes.has(item.k)) {
item.a?.measure();
to_animate.push(item);
}
}
}
resume_effect(item.e);
// 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) {
item = a_items[i];
index = map_get(indexes, item.k);
if (item !== current) {
if (seen.has(item)) {
if (matched.length < stashed.length) {
// more efficient to move later items to the front
var start = stashed[0];
var local_anchor = get_first_child(start);
var j;
resume_effect(item.e);
prev = start.prev;
if (index === undefined) {
to_destroy.push(item.e);
} else {
moved = true;
sources[index - start] = i;
b_items[index] = item;
var a = matched[0];
var b = matched[matched.length - 1];
if (is_animated) {
to_animate.push(item);
}
}
}
link(a.prev, b.next);
link(prev, a);
link(b, start);
// 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
// I fully understand this part)
if (moved) {
mark_lis(sources);
} else if (is_controlled && to_destroy.length === a_items.length) {
// We can optimize the case in which all items are replaced —
// destroy everything first, then append new items
pause_effects(to_destroy, anchor);
to_destroy = [];
}
for (j = 0; j < matched.length; j += 1) {
move(matched[j], local_anchor);
}
// working from the back, insert new or moved items
while (b-- > start) {
index = sources[b - start];
var should_insert = index === NEW_ITEM;
for (j = 0; j < stashed.length; j += 1) {
seen.delete(stashed[j]);
}
if (should_insert) {
if (last_item !== undefined) anchor = get_first_child(last_item);
item = create_item(anchor, array[b], keys[b], b, render_fn, flags);
} else {
item = b_items[b];
if (should_update) {
update_item(item, array[b], b, flags);
}
current = start;
prev = b;
i -= 1;
if (moved && index !== LIS_ITEM) {
if (last_item !== undefined) anchor = get_first_child(last_item);
move(/** @type {import('#client').Dom} */ (item.e.dom), anchor);
}
}
matched = [];
stashed = [];
} else {
// more efficient to move earlier items to the back
seen.delete(item);
move(item, current ? get_first_child(current) : anchor);
last_item = b_items[b] = item;
}
}
link(item.prev, item.next);
link(item, prev.next);
link(prev, item);
if (to_animate.length > 0) {
// TODO we need to briefly take any outroing elements out of the flow, so that
// we can figure out the eventual destination of the animating elements
// - https://github.com/sveltejs/svelte/pull/10798#issuecomment-2013681778
// - https://svelte.dev/repl/6e891305e9644a7ca7065fa95c79d2d2?version=4.2.9
effect(() => {
untrack(() => {
for (item of to_animate) {
item.a?.apply();
prev = item;
}
});
});
}
var controlled_anchor = is_controlled && b_items.length === 0 ? anchor : null;
continue;
}
pause_effects(to_destroy, controlled_anchor, () => {
state.items = b_items;
});
}
matched = [];
stashed = [];
/**
* Longest Increased Subsequence algorithm
* @param {Int32Array} a
* @returns {void}
*/
function mark_lis(a) {
var length = a.length;
var parent = new Int32Array(length);
var index = new Int32Array(length);
var index_length = 0;
var i = 0;
while (current !== null && current.k !== key) {
seen.add(current);
stashed.push(current);
current = current.next;
}
/** @type {number} */
var j;
if (current === null) {
continue;
}
/** @type {number} */
var k;
item = current;
}
/** @type {number} */
var lo;
matched.push(item);
prev = item;
current = item.next;
}
/** @type {number} */
var hi;
const to_destroy = Array.from(seen);
// Skip -1 values at the start of the input array `a`.
for (; a[i] === NEW_ITEM; ++i) {
/**/
while (current) {
to_destroy.push(current);
current = current.next;
}
index[0] = i++;
var controlled_anchor = (flags & EACH_IS_CONTROLLED) !== 0 && length === 0 ? anchor : null;
for (; i < length; ++i) {
k = a[i];
pause_effects(to_destroy, controlled_anchor, () => {
for (var i = 0; i < to_destroy.length; i += 1) {
var item = to_destroy[i];
items.delete(item.k);
link(item.prev, item.next);
}
});
if (k !== NEW_ITEM) {
// Ignore -1 values.
j = index[index_length];
if (a[j] < k) {
parent[i] = j;
index[++index_length] = i;
} else {
lo = 0;
hi = index_length;
while (lo < hi) {
j = (lo + hi) >> 1;
if (a[index[j]] < k) {
lo = j + 1;
} else {
hi = j;
}
if (is_animated) {
effect(() => {
untrack(() => {
for (item of to_animate) {
item.a?.apply();
}
if (k < a[index[lo]]) {
if (lo > 0) {
parent[i] = index[lo - 1];
}
index[lo] = i;
}
}
}
});
});
}
// Mutate input array `a` and assign -2 value to all nodes that are part of LIS.
j = index[index_length];
while (index_length-- >= 0) {
a[j] = LIS_ITEM;
j = parent[j];
}
}

@@ -593,2 +449,4 @@

* @param {Node} anchor
* @param {import('#client').EachItem | import('#client').EachState} prev
* @param {import('#client').EachItem | null} next
* @param {V} value

@@ -601,3 +459,3 @@ * @param {unknown} key

*/
function create_item(anchor, value, key, index, render_fn, flags) {
function create_item(anchor, prev, next, value, key, index, render_fn, flags) {
var previous_each_item = current_each_item;

@@ -619,5 +477,10 @@

// @ts-expect-error
e: null
e: null,
prev,
next
};
prev.next = item;
if (next !== null) next.prev = item;
current_each_item = item;

@@ -633,13 +496,27 @@ item.e = branch(() => render_fn(anchor, v, i));

/**
* @param {import('#client').Dom} current
* @param {import('#client').EachItem} item
* @param {Text | Element | Comment} anchor
*/
function move(current, anchor) {
if (is_array(current)) {
for (var i = 0; i < current.length; i++) {
anchor.before(current[i]);
function move(item, anchor) {
var dom = item.e.dom;
if (dom !== null) {
if (is_array(dom)) {
for (var i = 0; i < dom.length; i++) {
anchor.before(dom[i]);
}
} else {
anchor.before(dom);
}
} else {
anchor.before(current);
}
}
/**
*
* @param {import('#client').EachItem | import('#client').EachState} prev
* @param {import('#client').EachItem | null} next
*/
function link(prev, next) {
prev.next = next;
if (next !== null) next.prev = prev;
}

@@ -101,4 +101,2 @@ import { noop } from '../../../shared/utils.js';

const options = get_fn()(this.element, { from, to }, get_params?.());
if (

@@ -110,2 +108,4 @@ from.left !== to.left ||

) {
const options = get_fn()(this.element, { from, to }, get_params?.());
animation = animate(this.element, options, undefined, 1, () => {

@@ -112,0 +112,0 @@ animation?.abort();

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

export { hmr } from './dev/hmr.js';
export { add_owner, mark_module_start, mark_module_end } from './dev/ownership.js';

@@ -6,3 +7,3 @@ export { await_block as await } from './dom/blocks/await.js';

export { css_props } from './dom/blocks/css-props.js';
export { each_keyed, each_indexed } from './dom/blocks/each.js';
export { index, each } from './dom/blocks/each.js';
export { html } from './dom/blocks/html.js';

@@ -9,0 +10,0 @@ export { snippet } from './dom/blocks/snippet.js';

@@ -22,3 +22,2 @@ import { DEV } from 'esm-env';

import { STATE_SYMBOL } from './constants.js';
import { updating_derived } from './reactivity/deriveds.js';
import { UNINITIALIZED } from '../../constants.js';

@@ -211,9 +210,4 @@

// if we're reading a property in a reactive context, create a source,
// but only if it's an own property and not a prototype property
if (
s === undefined &&
(current_effect !== null || updating_derived) &&
(!(prop in target) || get_descriptor(target, prop)?.writable)
) {
// create a source, but only if it's an own property and not a prototype property
if (s === undefined && (!(prop in target) || get_descriptor(target, prop)?.writable)) {
s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i, metadata.o));

@@ -286,3 +280,3 @@ metadata.s.set(prop, s);

// object property before writing to that property.
if (s === undefined && current_effect !== null) {
if (s === undefined) {
// the read creates a signal

@@ -289,0 +283,0 @@ untrack(() => receiver[prop]);

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

import { HYDRATION_START, PassiveDelegatedEvents } from '../../constants.js';
import { flush_sync, push, pop, current_component_context, untrack } from './runtime.js';
import { flush_sync, push, pop, current_component_context } from './runtime.js';
import { effect_root, branch } from './reactivity/effects.js';

@@ -13,0 +13,0 @@ import {

@@ -53,4 +53,6 @@ import type { Store } from '#shared';

flags: number;
/** items */
items: EachItem[];
/** a key -> item lookup */
items: Map<any, EachItem>;
/** head of the linked list of items */
next: EachItem | null;
};

@@ -69,2 +71,4 @@

k: unknown;
prev: EachItem | EachState;
next: EachItem | null;
};

@@ -71,0 +75,0 @@

@@ -56,3 +56,3 @@ import { proxy } from '../internal/client/proxy.js';

/** @type {any} */
#events = {};
#events;

@@ -74,3 +74,3 @@ /** @type {Record<string, any>} */

// Reactive statements and actions (the things where this matters) are handling this properly regardless, so it should be fine in practise.
const props = proxy({ ...(options.props || {}), $$events: this.#events }, false);
const props = proxy({ ...(options.props || {}), $$events: {} }, false);
this.#instance = (options.hydrate ? hydrate : mount)(options.component, {

@@ -84,2 +84,4 @@ target: options.target,

this.#events = props.$$events;
for (const key of Object.keys(this.#instance)) {

@@ -86,0 +88,0 @@ if (key === '$set' || key === '$destroy' || key === '$on') continue;

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

*/
export const VERSION = '5.0.0-next.96';
export const VERSION = '5.0.0-next.97';
export const PUBLIC_VERSION = '5';

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