Skip to content

Commit bb547bc

Browse files
committed
WIP
1 parent de12984 commit bb547bc

File tree

5 files changed

+36
-20
lines changed

5 files changed

+36
-20
lines changed

packages/svelte/src/ambient.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ declare namespace $effect {
255255
*/
256256
export function pre(fn: () => void | (() => void)): void;
257257

258-
export function lazy(state: any, fn: () => void | (() => void)): void;
258+
export function lazy(state: any[], fn: () => void | (() => void)): void;
259259

260260
/**
261261
* The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,28 @@ export function CallExpression(node, context) {
103103
}
104104
const state_ref = node.arguments[0];
105105

106-
if (state_ref.type !== 'Identifier') {
107-
throw new Error('Bad $effect.lazy, first argument must be an identifier');
106+
if (state_ref.type !== 'ArrayExpression') {
107+
throw new Error('Bad $effect.lazy, first argument must be an array of $state references');
108108
}
109109
const scope = context.state.scope;
110-
const binding = /** @type {Binding} */ (scope.get(state_ref.name));
111-
112-
if (binding === null || binding.kind !== 'state') {
113-
throw new Error('Bad $effect.lazy link, must be a local reference to $state');
110+
for (const element of state_ref.elements) {
111+
if (element === null || element.type !== 'Identifier') {
112+
throw new Error(
113+
'Bad $effect.lazy, first argument must be an array of $state references'
114+
);
115+
}
116+
117+
const binding = /** @type {Binding} */ (scope.get(element.name));
118+
119+
if (binding === null || binding.kind !== 'state') {
120+
throw new Error('Bad $effect.lazy link, must be a local reference to $state');
121+
}
122+
const id = scope.generate('effect');
123+
(binding.linked_effects ??= []).push(id);
124+
/** @type {SimpleCallExpression} */ (node).metadata = {
125+
id
126+
};
114127
}
115-
const id = scope.generate('effect');
116-
(binding.linked_effects ??= []).push(id);
117-
/** @type {SimpleCallExpression} */ (node).metadata = {
118-
id
119-
};
120128
} else if (node.arguments.length !== 1) {
121129
e.rune_invalid_arguments_length(node, rune, 'exactly one argument');
122130
}

packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { Expression, Property, ExpressionStatement, ObjectExpression, Identifier } from 'estree' */
1+
/** @import { Expression, Property, ExpressionStatement, ObjectExpression, Identifier, ArrayExpression } from 'estree' */
22
/** @import { ComponentContext } from '../types' */
33
import * as b from '../../../../utils/builders.js';
44
import { get_rune } from '../../../scope.js';
@@ -26,7 +26,7 @@ export function ExpressionStatement(node, context) {
2626
const expr = b.call(
2727
'$.lazy_effect',
2828
/** @type {Expression} */ (func),
29-
/** @type {Identifier} */ (node.expression.arguments[0])
29+
/** @type {ArrayExpression} */ (node.expression.arguments[0])
3030
);
3131
expr.callee.loc = node.expression.callee.loc; // ensure correct mapping
3232

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, Reaction, TemplateNode, TransitionManager } from '#client' */
1+
/** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, TemplateNode, TransitionManager } from '#client' */
22
import {
33
check_dirtiness,
44
component_context,
@@ -16,7 +16,8 @@ import {
1616
set_is_flushing_effect,
1717
set_signal_status,
1818
untrack,
19-
skip_reaction
19+
skip_reaction,
20+
new_deps
2021
} from '../runtime.js';
2122
import {
2223
DIRTY,
@@ -221,10 +222,10 @@ export function user_effect(fn) {
221222
/**
222223
* Internal representation of `$effect.lazy(...)`
223224
* @param {() => void | (() => void)} fn
224-
* @param {Derived} state
225+
* @param {Derived[]} states
225226
* @returns {Effect}
226227
*/
227-
export function lazy_effect(fn, state) {
228+
export function lazy_effect(fn, states) {
228229
validate_effect('$effect.lazy');
229230
if (DEV) {
230231
define_property(fn, 'name', {
@@ -236,8 +237,15 @@ export function lazy_effect(fn, state) {
236237
LAZY_EFFECT,
237238
() => {
238239
var teardown = fn();
240+
if (new_deps !== null) {
241+
for (var i = new_deps.length - 1; i >= 0; i--) {
242+
if (states.includes(/** @type {Derived} */ (new_deps[i]))) {
243+
new_deps.splice(i, 1);
244+
}
245+
}
246+
}
239247
var current_effect = /** @type {Effect} */ (active_reaction);
240-
(current_effect.deriveds ??= []).push(state);
248+
(current_effect.deriveds ??= []).push(...states);
241249

242250
return teardown;
243251
},

packages/svelte/types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2569,7 +2569,7 @@ declare namespace $effect {
25692569
*/
25702570
export function pre(fn: () => void | (() => void)): void;
25712571

2572-
export function lazy(state: any, fn: () => void | (() => void)): void;
2572+
export function lazy(state: any[], fn: () => void | (() => void)): void;
25732573

25742574
/**
25752575
* The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

0 commit comments

Comments
 (0)