Skip to content

Commit cf91306

Browse files
authored
feat: add $effect.active rune (#9591)
* chore: add $effect.active rune * chore: add $effect.active rune
1 parent 13aef52 commit cf91306

File tree

9 files changed

+87
-5
lines changed

9 files changed

+87
-5
lines changed

.changeset/popular-mangos-rest.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
feat: add $effect.active rune

packages/svelte/src/compiler/phases/2-analyze/validation.js

+11
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,17 @@ function validate_call_expression(node, scope, path) {
504504
}
505505

506506
if (rune === '$effect') {
507+
const callee = node.callee;
508+
if (
509+
callee.type === 'MemberExpression' &&
510+
callee.property.type === 'Identifier' &&
511+
callee.property.name === 'active'
512+
) {
513+
if (node.arguments.length !== 0) {
514+
error(node, 'invalid-rune-args-length', '$effect.active', [0]);
515+
}
516+
return;
517+
}
507518
if (parent.type !== 'ExpressionStatement') {
508519
error(node, 'invalid-effect-location');
509520
}

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export const javascript_visitors_runes = {
135135
for (const declarator of node.declarations) {
136136
const init = declarator.init;
137137
const rune = get_rune(init, state.scope);
138-
if (!rune) {
138+
if (!rune || rune === '$effect') {
139139
if (init != null && is_hoistable_function(init)) {
140140
const hoistable_function = visit(init);
141141
state.hoisted.push(
@@ -291,5 +291,19 @@ export const javascript_visitors_runes = {
291291
}
292292

293293
context.next();
294+
},
295+
CallExpression(node, { state, next }) {
296+
const rune = get_rune(node, state.scope);
297+
const callee = node.callee;
298+
299+
if (
300+
rune === '$effect' &&
301+
callee.type === 'MemberExpression' &&
302+
callee.property.type === 'Identifier' &&
303+
callee.property.name === 'active'
304+
) {
305+
return b.call('$.effect_active');
306+
}
307+
next();
294308
}
295309
};

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
EACH_KEYED
3636
} from '../../../../../constants.js';
3737
import { regex_is_valid_identifier } from '../../../patterns.js';
38+
import { javascript_visitors_runes } from './javascript-runes.js';
3839

3940
/**
4041
* Serializes each style directive into something like `$.style(element, style_property, value)`
@@ -2921,5 +2922,6 @@ export const template_visitors = {
29212922
...context.state,
29222923
node: b.id('$.document')
29232924
});
2924-
}
2925+
},
2926+
CallExpression: javascript_visitors_runes.CallExpression
29252927
};

packages/svelte/src/compiler/phases/3-transform/server/transform-server.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ const javascript_visitors_runes = {
550550

551551
for (const declarator of node.declarations) {
552552
const rune = get_rune(declarator.init, state.scope);
553-
if (!rune) {
553+
if (!rune || rune === '$effect') {
554554
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
555555
continue;
556556
}
@@ -604,6 +604,20 @@ const javascript_visitors_runes = {
604604
}
605605
}
606606
context.next();
607+
},
608+
CallExpression(node, { state, next }) {
609+
const rune = get_rune(node, state.scope);
610+
const callee = node.callee;
611+
612+
if (
613+
rune === '$effect' &&
614+
callee.type === 'MemberExpression' &&
615+
callee.property.type === 'Identifier' &&
616+
callee.property.name === 'active'
617+
) {
618+
return b.literal(false);
619+
}
620+
next();
607621
}
608622
};
609623

@@ -1579,7 +1593,9 @@ const template_visitors = {
15791593
b.stmt(b.call('$.head', b.id('$$payload'), b.arrow([b.id('$$payload')], b.block(body))))
15801594
)
15811595
);
1582-
}
1596+
},
1597+
// @ts-ignore: need to extract this out somehow
1598+
CallExpression: javascript_visitors_runes.CallExpression
15831599
};
15841600

15851601
/**

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

+7
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,13 @@ function internal_create_effect(type, init, sync, block, schedule) {
11431143
return signal;
11441144
}
11451145

1146+
/**
1147+
* @returns {boolean}
1148+
*/
1149+
export function effect_active() {
1150+
return current_effect ? (current_effect.f & MANAGED) === 0 : false;
1151+
}
1152+
11461153
/**
11471154
* @param {() => void | (() => void)} init
11481155
* @returns {import('./types.js').EffectSignal}

packages/svelte/src/internal/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export {
3535
onDestroy,
3636
pop,
3737
push,
38-
reactive_import
38+
reactive_import,
39+
effect_active
3940
} from './client/runtime.js';
4041

4142
export * from './client/validate.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
ssrHtml: `
5+
<p>false</p>
6+
<p>false</p>
7+
<p>false</p>
8+
`,
9+
10+
html: `
11+
<p>false</p>
12+
<p>true</p>
13+
<p>true</p>
14+
`
15+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
const foo = $effect.active();
3+
let bar = $state(false);
4+
$effect.pre(() => {
5+
bar = $effect.active();
6+
});
7+
</script>
8+
9+
<p>{foo}</p>
10+
<p>{bar}</p>
11+
<p>{$effect.active()}</p>

0 commit comments

Comments
 (0)