breaking: rename $effect.active to $effect.tracking (#12022)

* breaking: rename $effect.active to $effect.tracking

* update type

* add more helpful error

* tweak changeset

* fix prettier config

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/12015/head
Dominic Gannaway 4 months ago committed by GitHub
parent 9dc2d71a12
commit ccb3c90cd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
breaking: rename `$effect.active` to `$effect.tracking`

@ -114,6 +114,10 @@
> Cannot use rune without parentheses
## rune_renamed
> `%name%` is now `%replacement%`
## runes_mode_invalid_import
> %name% cannot be used in runes mode

@ -201,26 +201,26 @@ declare namespace $effect {
export function pre(fn: () => void | (() => void)): void;
/**
* The `$effect.active` rune is an advanced feature that tells you whether or not the code is running inside an effect or inside your template.
* 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.
*
* Example:
* ```svelte
* <script>
* console.log('in component setup:', $effect.active()); // false
* console.log('in component setup:', $effect.tracking()); // false
*
* $effect(() => {
* console.log('in effect:', $effect.active()); // true
* console.log('in effect:', $effect.tracking()); // true
* });
* </script>
*
* <p>in template: {$effect.active()}</p> <!-- true -->
* <p>in template: {$effect.tracking()}</p> <!-- true -->
* ```
*
* This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.
*
* https://svelte-5-preview.vercel.app/docs/runes#$effect-active
* https://svelte-5-preview.vercel.app/docs/runes#$effect-tracking
*/
export function active(): boolean;
export function tracking(): boolean;
/**
* The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for

@ -363,6 +363,17 @@ export function rune_missing_parentheses(node) {
e(node, "rune_missing_parentheses", "Cannot use rune without parentheses");
}
/**
* `%name%` is now `%replacement%`
* @param {null | number | NodeLike} node
* @param {string} name
* @param {string} replacement
* @returns {never}
*/
export function rune_renamed(node, name, replacement) {
e(node, "rune_renamed", `\`${name}\` is now \`${replacement}\``);
}
/**
* %name% cannot be used in runes mode
* @param {null | number | NodeLike} node

@ -880,7 +880,7 @@ function validate_call_expression(node, scope, path) {
}
}
if (rune === '$effect.active') {
if (rune === '$effect.tracking') {
if (node.arguments.length !== 0) {
e.rune_invalid_arguments(node, rune);
}
@ -1141,6 +1141,10 @@ export const validation_runes = merge(validation, a11y_validators, {
parent = /** @type {import('estree').Expression} */ (path[--i]);
if (!Runes.includes(/** @type {Runes[number]} */ (name))) {
if (name === '$effect.active') {
e.rune_renamed(parent, '$effect.active', '$effect.tracking');
}
e.rune_invalid_name(parent, name);
}
}

@ -215,7 +215,7 @@ export const javascript_visitors_runes = {
const rune = get_rune(init, state.scope);
if (
!rune ||
rune === '$effect.active' ||
rune === '$effect.tracking' ||
rune === '$effect.root' ||
rune === '$inspect' ||
rune === '$state.snapshot' ||
@ -434,8 +434,8 @@ export const javascript_visitors_runes = {
return b.id('$$props.$$host');
}
if (rune === '$effect.active') {
return b.call('$.effect_active');
if (rune === '$effect.tracking') {
return b.call('$.effect_tracking');
}
if (rune === '$state.snapshot') {

@ -407,7 +407,7 @@ const global_visitors = {
return b.id('undefined');
}
if (rune === '$effect.active') {
if (rune === '$effect.tracking') {
return b.literal(false);
}
@ -571,7 +571,7 @@ const javascript_visitors_runes = {
for (const declarator of node.declarations) {
const init = declarator.init;
const rune = get_rune(init, state.scope);
if (!rune || rune === '$effect.active' || rune === '$inspect') {
if (!rune || rune === '$effect.tracking' || rune === '$inspect') {
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
continue;
}

@ -39,7 +39,7 @@ export const Runes = /** @type {const} */ ([
'$derived.by',
'$effect',
'$effect.pre',
'$effect.active',
'$effect.tracking',
'$effect.root',
'$inspect',
'$inspect().with',

@ -90,7 +90,7 @@ export {
} from './dom/template.js';
export { derived, derived_safe_equal } from './reactivity/deriveds.js';
export {
effect_active,
effect_tracking,
effect_root,
legacy_pre_effect,
legacy_pre_effect_reset,

@ -139,10 +139,13 @@ function create_effect(type, fn, sync) {
}
/**
* Internal representation of `$effect.active()`
* Internal representation of `$effect.tracking()`
* @returns {boolean}
*/
export function effect_active() {
export function effect_tracking() {
if (current_untracking) {
return false;
}
if (current_reaction && (current_reaction.f & DERIVED) !== 0) {
return (current_reaction.f & UNOWNED) === 0;
}

@ -1,7 +1,7 @@
<script>
let value = $state(false);
const fn = () => {
if ($effect.active()) {
if ($effect.tracking()) {
$effect(() => {
value = true;
});

@ -1,11 +0,0 @@
<script>
const foo = $effect.active();
let bar = $state(false);
$effect.pre(() => {
bar = $effect.active();
});
</script>
<p>{foo}</p>
<p>{bar}</p>
<p>{$effect.active()}</p>

@ -5,11 +5,13 @@ export default test({
<p>false</p>
<p>false</p>
<p>false</p>
<p>false</p>
`,
html: `
<p>false</p>
<p>true</p>
<p>true</p>
<p>false</p>
`
});

@ -0,0 +1,14 @@
<script>
import {untrack} from 'svelte';
const foo = $effect.tracking();
let bar = $state(false);
$effect.pre(() => {
bar = $effect.tracking();
});
</script>
<p>{foo}</p>
<p>{bar}</p>
<p>{$effect.tracking()}</p>
<p>{untrack(() => $effect.tracking())}</p>

@ -2830,26 +2830,26 @@ declare namespace $effect {
export function pre(fn: () => void | (() => void)): void;
/**
* The `$effect.active` rune is an advanced feature that tells you whether or not the code is running inside an effect or inside your template.
* 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.
*
* Example:
* ```svelte
* <script>
* console.log('in component setup:', $effect.active()); // false
* console.log('in component setup:', $effect.tracking()); // false
*
* $effect(() => {
* console.log('in effect:', $effect.active()); // true
* console.log('in effect:', $effect.tracking()); // true
* });
* </script>
*
* <p>in template: {$effect.active()}</p> <!-- true -->
* <p>in template: {$effect.tracking()}</p> <!-- true -->
* ```
*
* This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.
*
* https://svelte-5-preview.vercel.app/docs/runes#$effect-active
* https://svelte-5-preview.vercel.app/docs/runes#$effect-tracking
*/
export function active(): boolean;
export function tracking(): boolean;
/**
* The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for

@ -119,7 +119,7 @@ const runes = [
{ snippet: '$effect.root(() => {\n\t${}\n})' },
{ snippet: '$state.snapshot(${})' },
{ snippet: '$state.is(${})' },
{ snippet: '$effect.active()' },
{ snippet: '$effect.tracking()' },
{ snippet: '$inspect(${});', test: is_statement }
];

@ -436,20 +436,20 @@ Apart from the timing, `$effect.pre` works exactly like [`$effect`](#$effect)
Previously, you would have used `beforeUpdate`, which — like `afterUpdate` — is deprecated in Svelte 5.
## `$effect.active`
## `$effect.tracking`
The `$effect.active` rune is an advanced feature that tells you whether or not the code is running inside an effect or inside your template ([demo](/#H4sIAAAAAAAAE3XP0QrCMAwF0F-JRXAD595rLfgdzodRUyl0bVgzQcb-3VYFQfExl5tDMgvrPCYhT7MI_YBCiiOR2Aq-UxnSDT1jnlOcRlMSlczoiHUXOjYxpOhx5-O12rgAJg4UAwaGhDyR3Gxhjdai4V1v2N2wqus9tC3Y3ifMQjbehaqq4aBhLtEv_Or893icCsdLve-Caj8nBkU67zMO5HtGCfM3sKiWNKhV0zwVaBqd3x3ixVmHFyFLuJyXB-moOe8pAQAA)):
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 ([demo](/#H4sIAAAAAAAAE3XP0QrCMAwF0F-JRXAD595rLfgdzodRUyl0bVgzQcb-3VYFQfExl5tDMgvrPCYhT7MI_YBCiiOR2Aq-UxnSDT1jnlOcRlMSlczoiHUXOjYxpOhx5-O12rgAJg4UAwaGhDyR3Gxhjdai4V1v2N2wqus9tC3Y3ifMQjbehaqq4aBhLtEv_Or893icCsdLve-Caj8nBkU67zMO5HtGCfM3sKiWNKhV0zwVaBqd3x3ixVmHFyFLuJyXB-moOe8pAQAA)):
```svelte
<script>
console.log('in component setup:', $effect.active()); // false
console.log('in component setup:', $effect.tracking()); // false
$effect(() => {
console.log('in effect:', $effect.active()); // true
console.log('in effect:', $effect.tracking()); // true
});
</script>
<p>in template: {$effect.active()}</p> <!-- true -->
<p>in template: {$effect.tracking()}</p> <!-- true -->
```
This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

Loading…
Cancel
Save