Skip to content

Commit

Permalink
breaking: rename $effect.active to $effect.tracking (sveltejs#12022)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
trueadm and Rich-Harris committed Jun 14, 2024
1 parent 9dc2d71 commit ccb3c90
Show file tree
Hide file tree
Showing 18 changed files with 73 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .changeset/khaki-cheetahs-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

breaking: rename `$effect.active` to `$effect.tracking`
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ sites/svelte.dev/src/lib/generated
.prettierignore
.changeset
pnpm-lock.yaml
pnpm-workspace.yaml
pnpm-workspace.yaml
4 changes: 4 additions & 0 deletions packages/svelte/messages/compile-errors/script.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions packages/svelte/src/ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions packages/svelte/src/compiler/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion packages/svelte/src/compiler/phases/2-analyze/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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' ||
Expand Down Expand Up @@ -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') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ const global_visitors = {
return b.id('undefined');
}

if (rune === '$effect.active') {
if (rune === '$effect.tracking') {
return b.literal(false);
}

Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/src/compiler/phases/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const Runes = /** @type {const} */ ([
'$derived.by',
'$effect',
'$effect.pre',
'$effect.active',
'$effect.tracking',
'$effect.root',
'$inspect',
'$inspect().with',
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/src/internal/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 5 additions & 2 deletions packages/svelte/src/internal/client/reactivity/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
let value = $state(false);
const fn = () => {
if ($effect.active()) {
if ($effect.tracking()) {
$effect(() => {
value = true;
});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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>
`
});
Original file line number Diff line number Diff line change
@@ -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>
12 changes: 6 additions & 6 deletions packages/svelte/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion sites/svelte-5-preview/src/lib/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit ccb3c90

Please sign in to comment.