Skip to content

Commit d41d0c2

Browse files
authored
chore: rename $derived.call to $derived.by (#10445)
* rename $derived.call to $derived.by * more replacements, plus a compiler error * regenerate types --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 9cee83c commit d41d0c2

File tree

15 files changed

+41
-34
lines changed

15 files changed

+41
-34
lines changed

.changeset/dirty-donuts-yell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
breaking: replace `$derived.call` with `$derived.by`

packages/svelte/src/compiler/errors.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ const runes = {
208208
'invalid-runes-mode-import': (name) => `${name} cannot be used in runes mode`,
209209
'duplicate-props-rune': () => `Cannot use $props() more than once`,
210210
'invalid-each-assignment': () =>
211-
`Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. 'array[i] = value' instead of 'entry = value')`
211+
`Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. 'array[i] = value' instead of 'entry = value')`,
212+
'invalid-derived-call': () => `$derived.call(...) has been replaced with $derived.by(...)`
212213
};
213214

214215
/** @satisfies {Errors} */

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ const runes_scope_js_tweaker = {
681681
rune !== '$state' &&
682682
rune !== '$state.frozen' &&
683683
rune !== '$derived' &&
684-
rune !== '$derived.call'
684+
rune !== '$derived.by'
685685
)
686686
return;
687687

@@ -717,7 +717,7 @@ const runes_scope_tweaker = {
717717
rune !== '$state' &&
718718
rune !== '$state.frozen' &&
719719
rune !== '$derived' &&
720-
rune !== '$derived.call' &&
720+
rune !== '$derived.by' &&
721721
rune !== '$props'
722722
)
723723
return;
@@ -730,7 +730,7 @@ const runes_scope_tweaker = {
730730
? 'state'
731731
: rune === '$state.frozen'
732732
? 'frozen_state'
733-
: rune === '$derived' || rune === '$derived.call'
733+
: rune === '$derived' || rune === '$derived.by'
734734
? 'derived'
735735
: path.is_rest
736736
? 'rest_prop'

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ function validate_call_expression(node, scope, path) {
746746
error(node, 'invalid-props-location');
747747
}
748748

749-
if (rune === '$state' || rune === '$derived' || rune === '$derived.call') {
749+
if (rune === '$state' || rune === '$derived' || rune === '$derived.by') {
750750
if (parent.type === 'VariableDeclarator') return;
751751
if (parent.type === 'PropertyDefinition' && !parent.static && !parent.computed) return;
752752
error(node, 'invalid-state-location', rune);
@@ -817,7 +817,7 @@ export const validation_runes_js = {
817817

818818
const args = /** @type {import('estree').CallExpression} */ (init).arguments;
819819

820-
if ((rune === '$derived' || rune === '$derived.call') && args.length !== 1) {
820+
if ((rune === '$derived' || rune === '$derived.by') && args.length !== 1) {
821821
error(node, 'invalid-rune-args-length', rune, [1]);
822822
} else if (rune === '$state' && args.length > 1) {
823823
error(node, 'invalid-rune-args-length', rune, [0, 1]);
@@ -842,7 +842,7 @@ export const validation_runes_js = {
842842
definition.value?.type === 'CallExpression'
843843
) {
844844
const rune = get_rune(definition.value, context.state.scope);
845-
if (rune === '$derived' || rune === '$derived.call') {
845+
if (rune === '$derived' || rune === '$derived.by') {
846846
private_derived_state.push(definition.key.name);
847847
}
848848
}
@@ -988,7 +988,7 @@ export const validation_runes = merge(validation, a11y_validators, {
988988
const args = /** @type {import('estree').CallExpression} */ (init).arguments;
989989

990990
// TODO some of this is duplicated with above, seems off
991-
if ((rune === '$derived' || rune === '$derived.call') && args.length !== 1) {
991+
if ((rune === '$derived' || rune === '$derived.by') && args.length !== 1) {
992992
error(node, 'invalid-rune-args-length', rune, [1]);
993993
} else if (rune === '$state' && args.length > 1) {
994994
error(node, 'invalid-rune-args-length', rune, [0, 1]);

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const javascript_visitors_runes = {
3333
rune === '$state' ||
3434
rune === '$state.frozen' ||
3535
rune === '$derived' ||
36-
rune === '$derived.call'
36+
rune === '$derived.by'
3737
) {
3838
/** @type {import('../types.js').StateField} */
3939
const field = {
@@ -42,7 +42,7 @@ export const javascript_visitors_runes = {
4242
? 'state'
4343
: rune === '$state.frozen'
4444
? 'frozen_state'
45-
: rune === '$derived.call'
45+
: rune === '$derived.by'
4646
? 'derived_call'
4747
: 'derived',
4848
// @ts-expect-error this is set in the next pass
@@ -289,12 +289,12 @@ export const javascript_visitors_runes = {
289289
continue;
290290
}
291291

292-
if (rune === '$derived' || rune === '$derived.call') {
292+
if (rune === '$derived' || rune === '$derived.by') {
293293
if (declarator.id.type === 'Identifier') {
294294
declarations.push(
295295
b.declarator(
296296
declarator.id,
297-
b.call('$.derived', rune === '$derived.call' ? value : b.thunk(value))
297+
b.call('$.derived', rune === '$derived.by' ? value : b.thunk(value))
298298
)
299299
);
300300
} else {
@@ -307,7 +307,7 @@ export const javascript_visitors_runes = {
307307
'$.derived',
308308
b.thunk(
309309
b.block([
310-
b.let(declarator.id, rune === '$derived.call' ? b.call(value) : value),
310+
b.let(declarator.id, rune === '$derived.by' ? b.call(value) : value),
311311
b.return(b.array(bindings.map((binding) => binding.node)))
312312
])
313313
)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ const javascript_visitors_runes = {
548548
: /** @type {import('estree').Expression} */ (visit(node.value.arguments[0]))
549549
};
550550
}
551-
if (rune === '$derived.call') {
551+
if (rune === '$derived.by') {
552552
return {
553553
...node,
554554
value:
@@ -582,7 +582,7 @@ const javascript_visitors_runes = {
582582
? b.id('undefined')
583583
: /** @type {import('estree').Expression} */ (visit(args[0]));
584584

585-
if (rune === '$derived.call') {
585+
if (rune === '$derived.by') {
586586
declarations.push(
587587
b.declarator(
588588
/** @type {import('estree').Pattern} */ (visit(declarator.id)),

packages/svelte/src/compiler/phases/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const Runes = /** @type {const} */ ([
3333
'$state.frozen',
3434
'$props',
3535
'$derived',
36-
'$derived.call',
36+
'$derived.by',
3737
'$effect',
3838
'$effect.pre',
3939
'$effect.active',

packages/svelte/src/compiler/phases/scope.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,8 @@ export function get_rune(node, scope) {
717717
if (n.type !== 'Identifier') return null;
718718

719719
joined = n.name + joined;
720+
721+
if (joined === '$derived.call') error(node, 'invalid-derived-call');
720722
if (!Runes.includes(/** @type {any} */ (joined))) return null;
721723

722724
const binding = scope.get(n.name);

packages/svelte/src/compiler/warnings.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ const runes = {
2424
/** @param {string} name */
2525
'non-state-reference': (name) =>
2626
`${name} is updated, but is not declared with $state(...). Changing its value will not correctly trigger updates.`,
27-
'derived-iife': () =>
28-
`Use \`$derived.call(() => {...})\` instead of \`$derived((() => {...})());\``
27+
'derived-iife': () => `Use \`$derived.by(() => {...})\` instead of \`$derived((() => {...})());\``
2928
};
3029

3130
/** @satisfies {Warnings} */

packages/svelte/src/main/ambient.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ declare function $derived<T>(expression: T): T;
6262
declare namespace $derived {
6363
/**
6464
* Sometimes you need to create complex derivations that don't fit inside a short expression.
65-
* In these cases, you can use `$derived.call` which accepts a function as its argument.
65+
* In these cases, you can use `$derived.by` which accepts a function as its argument.
6666
*
6767
* Example:
6868
* ```ts
69-
* let total = $derived.call(() => {
69+
* let total = $derived.by(() => {
7070
* let result = 0;
7171
* for (const n of numbers) {
7272
* result += n;
@@ -75,9 +75,9 @@ declare namespace $derived {
7575
* });
7676
* ```
7777
*
78-
* https://svelte-5-preview.vercel.app/docs/runes#$derived-call
78+
* https://svelte-5-preview.vercel.app/docs/runes#$derived-by
7979
*/
80-
export function call<T>(fn: () => T): T;
80+
export function by<T>(fn: () => T): T;
8181
}
8282

8383
/**

packages/svelte/tests/runtime-runes/samples/class-state-derived-fn/main.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script>
22
class Counter {
33
count = $state(0);
4-
doubled = $derived.call(() => this.count * 2);
4+
doubled = $derived.by(() => this.count * 2);
55
}
66
77
const counter = new Counter();
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script>
22
let count = $state(0);
3-
let double = $derived.call(() => count * 2);
3+
let double = $derived.by(() => count * 2);
44
</script>
55

66
<button on:click={() => count++}>{double}</button>

packages/svelte/types/index.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,11 +2501,11 @@ declare function $derived<T>(expression: T): T;
25012501
declare namespace $derived {
25022502
/**
25032503
* Sometimes you need to create complex derivations that don't fit inside a short expression.
2504-
* In these cases, you can use `$derived.call` which accepts a function as its argument.
2504+
* In these cases, you can use `$derived.by` which accepts a function as its argument.
25052505
*
25062506
* Example:
25072507
* ```ts
2508-
* let total = $derived.call(() => {
2508+
* let total = $derived.by(() => {
25092509
* let result = 0;
25102510
* for (const n of numbers) {
25112511
* result += n;
@@ -2514,9 +2514,9 @@ declare namespace $derived {
25142514
* });
25152515
* ```
25162516
*
2517-
* https://svelte-5-preview.vercel.app/docs/runes#$derived-call
2517+
* https://svelte-5-preview.vercel.app/docs/runes#$derived-by
25182518
*/
2519-
export function call<T>(fn: () => T): T;
2519+
export function by<T>(fn: () => T): T;
25202520
}
25212521

25222522
/**

sites/svelte-5-preview/src/lib/CodeMirror.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@
208208
{ label: '$state', type: 'keyword', boost: 10 },
209209
{ label: '$props', type: 'keyword', boost: 9 },
210210
{ label: '$derived', type: 'keyword', boost: 8 },
211-
snip('$derived.call(() => {\n\t${}\n});', {
212-
label: '$derived.call',
211+
snip('$derived.by(() => {\n\t${}\n});', {
212+
label: '$derived.by',
213213
type: 'keyword',
214214
boost: 7
215215
}),

sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,14 @@ If the value of a reactive variable is being computed it should be replaced with
134134
```
135135
...`double` will be calculated first despite the source order. In runes mode, `triple` cannot reference `double` before it has been declared.
136136

137-
## `$derived.call`
137+
## `$derived.by`
138138

139-
Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.call` which accepts a function as its argument.
139+
Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.by` which accepts a function as its argument.
140140

141141
```svelte
142142
<script>
143143
let numbers = $state([1, 2, 3]);
144-
let total = $derived.call(() => {
144+
let total = $derived.by(() => {
145145
let total = 0;
146146
for (const n of numbers) {
147147
total += n;
@@ -155,7 +155,7 @@ Sometimes you need to create complex derivations that don't fit inside a short e
155155
</button>
156156
```
157157

158-
In essence, `$derived(expression)` is equivalent to `$derived.call(() => expression)`.
158+
In essence, `$derived(expression)` is equivalent to `$derived.by(() => expression)`.
159159

160160
## `$effect`
161161

0 commit comments

Comments
 (0)