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`

@ -44,4 +44,4 @@ sites/svelte.dev/src/lib/generated
.prettierignore .prettierignore
.changeset .changeset
pnpm-lock.yaml pnpm-lock.yaml
pnpm-workspace.yaml pnpm-workspace.yaml

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

@ -201,26 +201,26 @@ declare namespace $effect {
export function pre(fn: () => void | (() => void)): void; 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: * Example:
* ```svelte * ```svelte
* <script> * <script>
* console.log('in component setup:', $effect.active()); // false * console.log('in component setup:', $effect.tracking()); // false
* *
* $effect(() => { * $effect(() => {
* console.log('in effect:', $effect.active()); // true * console.log('in effect:', $effect.tracking()); // true
* }); * });
* </script> * </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. * 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 * 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"); 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 * %name% cannot be used in runes mode
* @param {null | number | NodeLike} node * @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) { if (node.arguments.length !== 0) {
e.rune_invalid_arguments(node, rune); 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]); parent = /** @type {import('estree').Expression} */ (path[--i]);
if (!Runes.includes(/** @type {Runes[number]} */ (name))) { 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); e.rune_invalid_name(parent, name);
} }
} }

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

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

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

@ -90,7 +90,7 @@ export {
} from './dom/template.js'; } from './dom/template.js';
export { derived, derived_safe_equal } from './reactivity/deriveds.js'; export { derived, derived_safe_equal } from './reactivity/deriveds.js';
export { export {
effect_active, effect_tracking,
effect_root, effect_root,
legacy_pre_effect, legacy_pre_effect,
legacy_pre_effect_reset, 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} * @returns {boolean}
*/ */
export function effect_active() { export function effect_tracking() {
if (current_untracking) {
return false;
}
if (current_reaction && (current_reaction.f & DERIVED) !== 0) { if (current_reaction && (current_reaction.f & DERIVED) !== 0) {
return (current_reaction.f & UNOWNED) === 0; return (current_reaction.f & UNOWNED) === 0;
} }

@ -1,7 +1,7 @@
<script> <script>
let value = $state(false); let value = $state(false);
const fn = () => { const fn = () => {
if ($effect.active()) { if ($effect.tracking()) {
$effect(() => { $effect(() => {
value = true; 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>
<p>false</p> <p>false</p>
<p>false</p>
`, `,
html: ` html: `
<p>false</p> <p>false</p>
<p>true</p> <p>true</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; 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: * Example:
* ```svelte * ```svelte
* <script> * <script>
* console.log('in component setup:', $effect.active()); // false * console.log('in component setup:', $effect.tracking()); // false
* *
* $effect(() => { * $effect(() => {
* console.log('in effect:', $effect.active()); // true * console.log('in effect:', $effect.tracking()); // true
* }); * });
* </script> * </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. * 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 * 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: '$effect.root(() => {\n\t${}\n})' },
{ snippet: '$state.snapshot(${})' }, { snippet: '$state.snapshot(${})' },
{ snippet: '$state.is(${})' }, { snippet: '$state.is(${})' },
{ snippet: '$effect.active()' }, { snippet: '$effect.tracking()' },
{ snippet: '$inspect(${});', test: is_statement } { 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. 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 ```svelte
<script> <script>
console.log('in component setup:', $effect.active()); // false console.log('in component setup:', $effect.tracking()); // false
$effect(() => { $effect(() => {
console.log('in effect:', $effect.active()); // true console.log('in effect:', $effect.tracking()); // true
}); });
</script> </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. This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

Loading…
Cancel
Save