8000 fix: make deriveds on the server lazy again · sveltejs/svelte@e6c4e8c · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit e6c4e8c

Browse files
committed
fix: make deriveds on the server lazy again
Fixes a regression introduced in #15820: deriveds need to be lazily called on the server, too, since they can close over variables only later defined Fixes #15960
1 parent 7183886 commit e6c4e8c

File tree

7 files changed

+50
-10
lines changed

7 files changed

+50
-10
lines changed

.changeset/khaki-carrots-destroy.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+
fix: make deriveds on the server lazy again

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Identifier } from './visitors/Identifier.js';
2323
import { IfBlock } from './visitors/IfBlock.js';
2424
import { KeyBlock } from './visitors/KeyBlock.js';
2525
import { LabeledStatement } from './visitors/LabeledStatement.js';
26+
import { MemberExpression } from './visitors/MemberExpression.js';
2627
import { PropertyDefinition } from './visitors/PropertyDefinition.js';
2728
import { RegularElement } from './visitors/RegularElement.js';
2829
import { RenderTag } from './visitors/RenderTag.js';
@@ -48,6 +49,7 @@ const global_visitors = {
4849
ExpressionStatement,
4950
Identifier,
5051
LabeledStatement,
52+
MemberExpression,
5153
PropertyDefinition,
5254
UpdateExpression,
5355
VariableDeclaration

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ export function ClassBody(node, context) {
2222
const child_state = { ...context.state, state_fields };
2323

2424
for (const [name, field] of state_fields) {
25-
if (name[0] === '#') {
26-
continue;
27-
}
28-
2925
// insert backing fields for stuff declared in the constructor
3026
if (
3127
field &&
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/** @import { ClassBody, MemberExpression } from 'estree' */
2+
/** @import { Context } from '../types.js' */
3+
import * as b from '#compiler/builders';
4+
5+
/**
6+
* @param {MemberExpression} node
7+
* @param {Context} context
8+
*/
9+
export function MemberExpression(node, context) {
10+
if (
11+
context.state.analysis.runes &&
12+
node.object.type === 'ThisExpression' &&
13+
node.property.type === 'PrivateIdentifier'
14+
) {
15+
const field = context.state.state_fields?.get(`#${node.property.name}`);
16+
17+
if (field?.type === '$derived' || field?.type === '$derived.by') {
18+
return b.call(node);
19+
}
20+
}
21+
22+
context.next();
23+
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function PropertyDefinition(node, context) {
1111
if (context.state.analysis.runes && node.value != null && node.value.type === 'CallExpression') {
1212
const rune = get_rune(node.value, context.state.scope);
1313

14-
if (rune === '$state' || rune === '$state.raw' || rune === '$derived') {
14+
if (rune === '$state' || rune === '$state.raw') {
1515
return {
1616
...node,
1717
value:
@@ -21,13 +21,14 @@ export function PropertyDefinition(node, context) {
2121
};
2222
}
2323

24-
if (rune === '$derived.by') {
24+
if (rune === '$derived.by' || rune === '$derived') {
25+
const fn = /** @type {Expression} */ (context.visit(node.value.arguments[0]));
2526
return {
2627
...node,
2728
value:
2829
node.value.arguments.length === 0
2930
? null
30-
: b.call(/** @type {Expression} */ (context.visit(node.value.arguments[0])))
31+
: b.call('$.once', rune === '$derived' ? b.thunk(fn) : fn)
3132
};
3233
}
3334
}

packages/svelte/tests/runtime-runes/samples/class-state-derived-private/_config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default test({
55
html: `
66
<button>0</button>
77
<p>doubled: 0</p>
8+
<p>trippled: 0</p>
89
`,
910

1011
test({ assert, target }) {
@@ -17,6 +18,7 @@ export default test({
1718
`
1819
<button>1</button>
1920
<p>doubled: 2</p>
21+
<p>trippled: 3</p>
2022
`
2123
);
2224

@@ -27,6 +29,7 @@ export default test({
2729
`
2830
<button>2</button>
2931
<p>doubled: 4</p>
32+
<p>trippled: 9</p>
3033
`
3134
);
3235
}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,24 @@
22
class Counter {
33
count = $state(0);
44
#doubled = $derived(this.count * 2);
5+
#trippled = $derived.by(() => this.count * this.by);
56
6-
get embiggened() {
7+
constructor(by) {
8+
this.by = by;
9+
}
10+
11+
get embiggened1() {
712
return this.#doubled;
813
}
14+
15+
get embiggened2() {
16+
return this.#trippled;
17+
}
918
}
1019
11-
const counter = new Counter();
20+
const counter = new Counter(3);
1221
</script>
1322

1423
<button on:click={() => counter.count++}>{counter.count}</button>
15-
<p>doubled: {counter.embiggened}</p>
24+
<p>doubled: {counter.embiggened1}</p>
25+
<p>trippled: {counter.embiggened2}</p>

0 commit comments

Comments
 (0)
0