Skip to content

Commit 155e9ad

Browse files
committed
merge main
2 parents 86de897 + c8bbb15 commit 155e9ad

File tree

12 files changed

+308
-186
lines changed

12 files changed

+308
-186
lines changed

packages/svelte/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# svelte
22

3+
## 5.19.5
4+
5+
### Patch Changes
6+
7+
- fix: improve derived connection to ownership graph ([#15137](https://github.com/sveltejs/svelte/pull/15137))
8+
9+
- fix: correctly look for sibling elements inside blocks and components when pruning CSS ([#15106](https://github.com/sveltejs/svelte/pull/15106))
10+
311
## 5.19.4
412

513
### Patch Changes

packages/svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "svelte",
33
"description": "Cybernetically enhanced web apps",
44
"license": "MIT",
5-
"version": "5.19.4",
5+
"version": "5.19.5",
66
"type": "module",
77
"types": "./types/index.d.ts",
88
"engines": {

packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -638,19 +638,30 @@ function get_following_sibling_elements(element, include_self) {
638638
/** @type {Array<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} */
639639
const siblings = [];
640640

641-
// ...then walk them, starting from the node after the one
642-
// containing the element in question
641+
// ...then walk them, starting from the node containing the element in question
642+
// skipping nodes that appears before the element
643643

644644
const seen = new Set();
645+
let skip = true;
645646

646647
/** @param {Compiler.AST.SvelteNode} node */
647648
function get_siblings(node) {
648649
walk(node, null, {
649650
RegularElement(node) {
650-
siblings.push(node);
651+
if (node === element) {
652+
skip = false;
653+
if (include_self) siblings.push(node);
654+
} else if (!skip) {
655+
siblings.push(node);
656+
}
651657
},
652658
SvelteElement(node) {
653-
siblings.push(node);
659+
if (node === element) {
660+
skip = false;
661+
if (include_self) siblings.push(node);
662+
} else if (!skip) {
663+
siblings.push(node);
664+
}
654665
},
655666
RenderTag(node) {
656667
for (const snippet of node.metadata.snippets) {
@@ -663,14 +674,10 @@ function get_following_sibling_elements(element, include_self) {
663674
});
664675
}
665676

666-
for (const node of nodes.slice(nodes.indexOf(start) + 1)) {
677+
for (const node of nodes.slice(nodes.indexOf(start))) {
667678
get_siblings(node);
668679
}
669680

670-
if (include_self) {
671-
siblings.push(element);
672-
}
673-
674681
return siblings;
675682
}
676683

packages/svelte/src/internal/client/reactivity/deriveds.js

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,24 @@ import { component_context } from '../context.js';
3535
/*#__NO_SIDE_EFFECTS__*/
3636
export function derived(fn) {
3737
var flags = DERIVED | DIRTY;
38+
var parent_derived =
39+
active_reaction !== null && (active_reaction.f & DERIVED) !== 0
40+
? /** @type {Derived} */ (active_reaction)
41+
: null;
3842

39-
if (active_effect === null) {
43+
if (active_effect === null || (parent_derived !== null && (parent_derived.f & UNOWNED) !== 0)) {
4044
flags |= UNOWNED;
4145
} else {
4246
// Since deriveds are evaluated lazily, any effects created inside them are
4347
// created too late to ensure that the parent effect is added to the tree
4448
active_effect.f |= EFFECT_HAS_DERIVED;
4549
}
4650

47-
var parent_derived =
48-
active_reaction !== null && (active_reaction.f & DERIVED) !== 0
49-
? /** @type {Derived} */ (active_reaction)
50-
: null;
51-
5251
/** @type {Derived<V>} */
5352
const signal = {
54-
children: null,
5553
ctx: component_context,
5654
deps: null,
55+
effects: null,
5756
equals,
5857
f: flags,
5958
fn,
@@ -87,19 +86,14 @@ export function derived_safe_equal(fn) {
8786
* @param {Derived} derived
8887
* @returns {void}
8988
*/
90-
function destroy_derived_children(derived) {
91-
var children = derived.children;
92-
93-
if (children !== null) {
94-
derived.children = null;
95-
96-
for (var i = 0; i < children.length; i += 1) {
97-
var child = children[i];
98-
if ((child.f & DERIVED) !== 0) {
99-
destroy_derived(/** @type {Derived} */ (child));
100-
} else {
101-
destroy_effect(/** @type {Effect} */ (child));
102-
}
89+
export function destroy_derived_effects(derived) {
90+
var effects = derived.effects;
91+
92+
if (effects !== null) {
93+
derived.effects = null;
94+
95+
for (var i = 0; i < effects.length; i += 1) {
96+
destroy_effect(/** @type {Effect} */ (effects[i]));
10397
}
10498
}
10599
}
@@ -147,7 +141,7 @@ export function execute_derived(derived) {
147141

148142
stack.push(derived);
149143

150-
destroy_derived_children(derived);
144+
destroy_derived_effects(derived);
151145
value = update_reaction(derived);
152146
} finally {
153147
set_active_effect(prev_active_effect);
@@ -156,7 +150,7 @@ export function execute_derived(derived) {
156150
}
157151
} else {
158152
try {
159-
destroy_derived_children(derived);
153+
destroy_derived_effects(derived);
160154
value = update_reaction(derived);
161155
} finally {
162156
set_active_effect(prev_active_effect);
@@ -188,9 +182,9 @@ export function update_derived(derived) {
188182
* @returns {void}
189183
*/
190184
export function destroy_derived(derived) {
191-
destroy_derived_children(derived);
185+
destroy_derived_effects(derived);
192186
remove_reactions(derived, 0);
193187
set_signal_status(derived, DESTROYED);
194188

195-
derived.v = derived.children = derived.deps = derived.ctx = derived.reactions = null;
189+
derived.v = derived.deps = derived.ctx = derived.reactions = null;
196190
}

packages/svelte/src/internal/client/reactivity/effects.js

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function validate_effect(rune) {
5353
e.effect_orphan(rune);
5454
}
5555

56-
if (active_reaction !== null && (active_reaction.f & UNOWNED) !== 0) {
56+
if (active_reaction !== null && (active_reaction.f & UNOWNED) !== 0 && active_effect === null) {
5757
e.effect_in_unowned_derived();
5858
}
5959

@@ -99,7 +99,6 @@ function create_effect(type, fn, sync, push = true) {
9999
var effect = {
100100
ctx: component_context,
101101
deps: null,
102-
deriveds: null,
103102
nodes_start: null,
104103
nodes_end: null,
105104
f: type | DIRTY,
@@ -153,7 +152,7 @@ function create_effect(type, fn, sync, push = true) {
153152
// if we're in a derived, add the effect there too
154153
if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) {
155154
var derived = /** @type {Derived} */ (active_reaction);
156-
(derived.children ??= []).push(effect);
155+
(derived.effects ??= []).push(effect);
157156
}
158157
}
159158

@@ -395,22 +394,6 @@ export function execute_effect_teardown(effect) {
395394
}
396395
}
397396

398-
/**
399-
* @param {Effect} signal
400-
* @returns {void}
401-
*/
402-
export function destroy_effect_deriveds(signal) {
403-
var deriveds = signal.deriveds;
404-
405-
if (deriveds !== null) {
406-
signal.deriveds = null;
407-
408-
for (var i = 0; i < deriveds.length; i += 1) {
409-
destroy_derived(deriveds[i]);
410-
}
411-
}
412-
}
413-
414397
/**
415398
* @param {Effect} signal
416399
* @param {boolean} remove_dom
@@ -468,7 +451,6 @@ export function destroy_effect(effect, remove_dom = true) {
468451
}
469452

470453
destroy_effect_children(effect, remove_dom && !removed);
471-
destroy_effect_deriveds(effect);
472454
remove_reactions(effect, 0);
473455
set_signal_status(effect, DESTROYED);
474456

packages/svelte/src/internal/client/reactivity/types.d.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ export interface Reaction extends Signal {
3636
export interface Derived<V = unknown> extends Value<V>, Reaction {
3737
/** The derived function */
3838
fn: () => V;
39-
/** Reactions created inside this signal */
40-
children: null | Reaction[];
39+
/** Effects created inside this signal */
40+
effects: null | Effect[];
4141
/** Parent effect or derived */
4242
parent: Effect | Derived | null;
4343
}
@@ -51,8 +51,6 @@ export interface Effect extends Reaction {
5151
*/
5252
nodes_start: null | TemplateNode;
5353
nodes_end: null | TemplateNode;
54-
/** Reactions created inside this signal */
55-
deriveds: null | Derived[];
5654
/** The effect function */
5755
fn: null | (() => void | (() => void));
5856
/** The teardown function returned from the effect function */

packages/svelte/src/internal/client/runtime.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { define_property, get_descriptors, get_prototype_of, index_of } from '..
44
import {
55
destroy_block_effect_children,
66
destroy_effect_children,
7-
destroy_effect_deriveds,
87
execute_effect_teardown,
98
unlink_effect
109
} from './reactivity/effects.js';
@@ -28,7 +27,12 @@ import {
2827
} from './constants.js';
2928
import { flush_tasks } from './dom/task.js';
3029
import { internal_set } from './reactivity/sources.js';
31-
import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js';
30+
import {
31+
destroy_derived,
32+
destroy_derived_effects,
33+
execute_derived,
34+
update_derived
35+
} from './reactivity/deriveds.js';
3236
import * as e from './errors.js';
3337
import { FILENAME } from '../../constants.js';
3438
import { tracing_mode_flag } from '../flags/index.js';
@@ -405,7 +409,16 @@ export function update_reaction(reaction) {
405409
skipped_deps = 0;
406410
untracked_writes = null;
407411
active_reaction = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
408-
skip_reaction = !is_flushing_effect && (flags & UNOWNED) !== 0;
412+
// prettier-ignore
413+
skip_reaction =
414+
(flags & UNOWNED) !== 0 &&
415+
(!is_flushing_effect ||
416+
// If we were previously not in a reactive context and we're reading an unowned derived
417+
// that was created inside another reaction, then we don't fully know the real owner and thus
418+
// we need to skip adding any reactions for this unowned
419+
((previous_reaction === null || previous_untracking) &&
420+
/** @type {Derived} */ (reaction).parent !== null));
421+
409422
derived_sources = null;
410423
set_component_context(reaction.ctx);
411424
untracking = false;
@@ -513,6 +526,8 @@ function remove_reaction(signal, dependency) {
513526
if ((dependency.f & (UNOWNED | DISCONNECTED)) === 0) {
514527
dependency.f ^= DISCONNECTED;
515528
}
529+
// Disconnect any reactions owned by this reaction
530+
destroy_derived_effects(/** @type {Derived} **/ (dependency));
516531
remove_reactions(/** @type {Derived} **/ (dependency), 0);
517532
}
518533
}
@@ -560,7 +575,6 @@ export function update_effect(effect) {
560575
} else {
561576
destroy_effect_children(effect);
562577
}
563-
destroy_effect_deriveds(effect);
564578

565579
execute_effect_teardown(effect);
566580
var teardown = update_reaction(effect);
@@ -930,30 +944,20 @@ export function get(signal) {
930944
new_deps.push(signal);
931945
}
932946
}
933-
}
934-
935-
if (
947+
} else if (
936948
is_derived &&
937949
/** @type {Derived} */ (signal).deps === null &&
938-
(active_reaction === null || untracking || (active_reaction.f & DERIVED) !== 0)
950+
/** @type {Derived} */ (signal).effects === null
939951
) {
940952
var derived = /** @type {Derived} */ (signal);
941953
var parent = derived.parent;
942954

943955
if (parent !== null) {
944-
// Attach the derived to the nearest parent effect or derived
945-
if ((parent.f & DERIVED) !== 0) {
946-
var parent_derived = /** @type {Derived} */ (parent);
947-
948-
if (!parent_derived.children?.includes(derived)) {
949-
(parent_derived.children ??= []).push(derived);
950-
}
951-
} else {
952-
var parent_effect = /** @type {Effect} */ (parent);
953-
954-
if (!parent_effect.deriveds?.includes(derived)) {
955-
(parent_effect.deriveds ??= []).push(derived);
956-
}
956+
// If the derived is owned by another derived then mark it as unowned
957+
// as the derived value might have been referenced in a different context
958+
// since and thus its parent might not be its true owner anymore
959+
if ((parent.f & UNOWNED) === 0) {
960+
derived.f ^= UNOWNED;
957961
}
958962
}
959963
}

packages/svelte/src/version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
* The current version, as set in package.json.
55
* @type {string}
66
*/
7-
export const VERSION = '5.19.4';
7+
export const VERSION = '5.19.5';
88
export const PUBLIC_VERSION = '5';

0 commit comments

Comments
 (0)