Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/angry-plums-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

chore: improve should_proxy_or_freeze logic internally
32 changes: 25 additions & 7 deletions packages/svelte/src/compiler/phases/3-transform/client/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ export function serialize_set_binding(node, context, fallback, options) {
if (
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
Expand All @@ -310,7 +310,7 @@ export function serialize_set_binding(node, context, fallback, options) {
left,
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? private_state.kind === 'frozen_state'
? b.call('$.freeze', value)
: b.call('$.proxy', value)
Expand All @@ -330,7 +330,7 @@ export function serialize_set_binding(node, context, fallback, options) {
context.state.analysis.runes &&
public_state !== undefined &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
Expand Down Expand Up @@ -398,7 +398,7 @@ export function serialize_set_binding(node, context, fallback, options) {
b.id(left_name),
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? b.call('$.proxy', value)
: value
);
Expand All @@ -408,7 +408,7 @@ export function serialize_set_binding(node, context, fallback, options) {
b.id(left_name),
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? b.call('$.freeze', value)
: value
);
Expand Down Expand Up @@ -623,8 +623,11 @@ export function get_prop_source(binding, state, name, initial) {
return b.call('$.prop', ...args);
}

/** @param {import('estree').Expression} node */
export function should_proxy_or_freeze(node) {
/**
* @param {import('estree').Expression} node
* @param {import("../../scope.js").Scope | null} scope
*/
export function should_proxy_or_freeze(node, scope) {
if (
!node ||
node.type === 'Literal' ||
Expand All @@ -637,5 +640,20 @@ export function should_proxy_or_freeze(node) {
) {
return false;
}
if (node.type === 'Identifier' && scope !== null) {
const binding = scope.get(node.name);
// Let's see if the reference is something that can be proxied or frozen
if (
binding !== null &&
!binding.reassigned &&
binding.initial !== null &&
binding.initial.type !== 'FunctionDeclaration' &&
binding.initial.type !== 'ClassDeclaration' &&
binding.initial.type !== 'ImportDeclaration' &&
binding.initial.type !== 'EachBlock'
) {
return should_proxy_or_freeze(binding.initial, null);
}
}
return true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ export const javascript_visitors_runes = {

value =
field.kind === 'state'
? b.call('$.source', should_proxy_or_freeze(init) ? b.call('$.proxy', init) : init)
? b.call(
'$.source',
should_proxy_or_freeze(init, state.scope) ? b.call('$.proxy', init) : init
)
: field.kind === 'frozen_state'
? b.call(
'$.source',
should_proxy_or_freeze(init) ? b.call('$.freeze', init) : init
should_proxy_or_freeze(init, state.scope) ? b.call('$.freeze', init) : init
)
: b.call('$.derived', b.thunk(init));
} else {
Expand Down Expand Up @@ -238,7 +241,7 @@ export const javascript_visitors_runes = {
*/
const create_state_declarator = (id, value) => {
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
if (should_proxy_or_freeze(value)) {
if (should_proxy_or_freeze(value, state.scope)) {
value = b.call(rune === '$state' ? '$.proxy' : '$.freeze', value);
}
if (is_state_source(binding, state)) {
Expand Down