Skip to content

Commit bbee1fc

Browse files
authored
fix: don't try to add owners to non-$state class fields (#14533)
* fix: don't try to add owners to non-`$state` class fields `$state.raw` and `$derived(.by)` will not have a state symbol on them, potentially causing a disastrous amount of traversal to potentially not find any state symbol. So it's better to not traverse them. Potentially someone could create a `$state` while creating `$state.raw` or inside a `$derived.by`, but that feels so much of an edge case that it doesn't warrant a perf hit for the common case. Fixes #14491 * for bind:, too
1 parent b558852 commit bbee1fc

File tree

3 files changed

+40
-20
lines changed

3 files changed

+40
-20
lines changed

.changeset/giant-windows-dance.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: don't try to add owners to non-`$state` class fields

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,22 @@ export function ClassBody(node, context) {
184184
'method',
185185
b.id('$.ADD_OWNER'),
186186
[b.id('owner')],
187-
Array.from(public_state.keys()).map((name) =>
188-
b.stmt(
189-
b.call(
190-
'$.add_owner',
191-
b.call('$.get', b.member(b.this, b.private_id(name))),
192-
b.id('owner'),
193-
b.literal(false),
194-
is_ignored(node, 'ownership_invalid_binding') && b.true
187+
Array.from(public_state)
188+
// Only run ownership addition on $state fields.
189+
// Theoretically someone could create a `$state` while creating `$state.raw` or inside a `$derived.by`,
190+
// but that feels so much of an edge case that it doesn't warrant a perf hit for the common case.
191+
.filter(([_, { kind }]) => kind === 'state')
192+
.map(([name]) =>
193+
b.stmt(
194+
b.call(
195+
'$.add_owner',
196+
b.call('$.get', b.member(b.this, b.private_id(name))),
197+
b.id('owner'),
198+
b.literal(false),
199+
is_ignored(node, 'ownership_invalid_binding') && b.true
200+
)
195201
)
196-
)
197-
),
202+
),
198203
true
199204
)
200205
);

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/** @import { AST, TemplateNode } from '#compiler' */
33
/** @import { ComponentContext } from '../../types.js' */
44
import { dev, is_ignored } from '../../../../../state.js';
5-
import { get_attribute_chunks } from '../../../../../utils/ast.js';
5+
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
66
import * as b from '../../../../../utils/builders.js';
77
import { create_derived } from '../../utils.js';
88
import { build_bind_this, validate_binding } from '../shared/utils.js';
@@ -176,16 +176,26 @@ export function build_component(node, component_name, context, anchor = context.
176176
bind_this = attribute.expression;
177177
} else {
178178
if (dev) {
179-
binding_initializers.push(
180-
b.stmt(
181-
b.call(
182-
b.id('$.add_owner_effect'),
183-
b.thunk(expression),
184-
b.id(component_name),
185-
is_ignored(node, 'ownership_invalid_binding') && b.true
179+
const left = object(attribute.expression);
180+
let binding;
181+
if (left?.type === 'Identifier') {
182+
binding = context.state.scope.get(left.name);
183+
}
184+
// Only run ownership addition on $state fields.
185+
// Theoretically someone could create a `$state` while creating `$state.raw` or inside a `$derived.by`,
186+
// but that feels so much of an edge case that it doesn't warrant a perf hit for the common case.
187+
if (binding?.kind !== 'derived' && binding?.kind !== 'raw_state') {
188+
binding_initializers.push(
189+
b.stmt(
190+
b.call(
191+
b.id('$.add_owner_effect'),
192+
b.thunk(expression),
193+
b.id(component_name),
194+
is_ignored(node, 'ownership_invalid_binding') && b.true
195+
)
186196
)
187-
)
188-
);
197+
);
198+
}
189199
}
190200

191201
const is_store_sub =

0 commit comments

Comments
 (0)