Skip to content

Commit 5ddf4ea

Browse files
committed
chore: improve $state.frozen performance in prod
1 parent aa91ed2 commit 5ddf4ea

File tree

4 files changed

+32
-11
lines changed

4 files changed

+32
-11
lines changed

.changeset/silver-sheep-knock.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+
chore: improve $state.frozen performance in prod

packages/svelte/src/internal/client/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export const EFFECT_TRANSPARENT = 1 << 15;
1818
export const LEGACY_DERIVED_PROP = 1 << 16;
1919

2020
export const STATE_SYMBOL = Symbol('$state');
21+
export const STATE_FROZEN_SYMBOL = Symbol('$state.frozen');
2122
export const LOADING_ATTR_SYMBOL = Symbol('');

packages/svelte/src/internal/client/proxy.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,25 @@ import {
1818
} from './utils.js';
1919
import { check_ownership, widen_ownership } from './dev/ownership.js';
2020
import { mutable_source, source, set } from './reactivity/sources.js';
21-
import { STATE_SYMBOL } from './constants.js';
21+
import { STATE_FROZEN_SYMBOL, STATE_SYMBOL } from './constants.js';
2222
import { UNINITIALIZED } from '../../constants.js';
2323
import * as e from './errors.js';
2424

2525
/**
2626
* @template T
27-
* @param {T} value
27+
* @param {T} initial_value
2828
* @param {boolean} [immutable]
2929
* @param {import('#client').ProxyMetadata | null} [parent]
3030
* @param {import('#client').Source<T>} [prev] dev mode only
3131
* @returns {import('#client').ProxyStateObject<T> | T}
3232
*/
33-
export function proxy(value, immutable = true, parent = null, prev) {
34-
if (typeof value === 'object' && value != null && !is_frozen(value)) {
33+
export function proxy(initial_value, immutable = true, parent = null, prev) {
34+
if (typeof initial_value === 'object' && initial_value != null) {
35+
let value = initial_value;
36+
// If the object is frozen then snapshot the value
37+
if (is_frozen(value) || STATE_FROZEN_SYMBOL in value) {
38+
value = snapshot(value);
39+
}
3540
// If we have an existing proxy, return it...
3641
if (STATE_SYMBOL in value) {
3742
const metadata = /** @type {import('#client').ProxyMetadata<T>} */ (value[STATE_SYMBOL]);
@@ -94,7 +99,7 @@ export function proxy(value, immutable = true, parent = null, prev) {
9499
}
95100
}
96101

97-
return value;
102+
return initial_value;
98103
}
99104

100105
/**

packages/svelte/src/internal/client/runtime.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DEV } from 'esm-env';
2-
import { get_descriptors, get_prototype_of, is_frozen, object_freeze } from './utils.js';
2+
import { define_property, get_descriptors, get_prototype_of, is_frozen, object_freeze } from './utils.js';
33
import { snapshot } from './proxy.js';
44
import { destroy_effect, effect, execute_effect_teardown } from './reactivity/effects.js';
55
import {
@@ -17,7 +17,8 @@ import {
1717
BLOCK_EFFECT,
1818
ROOT_EFFECT,
1919
LEGACY_DERIVED_PROP,
20-
DISCONNECTED
20+
DISCONNECTED,
21+
STATE_FROZEN_SYMBOL,
2122
} from './constants.js';
2223
import { flush_tasks } from './dom/task.js';
2324
import { add_owner } from './dev/ownership.js';
@@ -1352,7 +1353,7 @@ if (DEV) {
13521353
}
13531354

13541355
/**
1355-
* Expects a value that was wrapped with `freeze` and makes it frozen.
1356+
* Expects a value that was wrapped with `freeze` and makes it frozen in DEV or adds a symbol in prod.
13561357
* @template T
13571358
* @param {T} value
13581359
* @returns {Readonly<T>}
@@ -1361,10 +1362,19 @@ export function freeze(value) {
13611362
if (typeof value === 'object' && value != null && !is_frozen(value)) {
13621363
// If the object is already proxified, then snapshot the value
13631364
if (STATE_SYMBOL in value) {
1364-
return object_freeze(snapshot(value));
1365+
value = snapshot(value);
1366+
}
1367+
// Freeze the object in DEV, add the symbol in prod
1368+
if (DEV) {
1369+
object_freeze(value);
1370+
} else {
1371+
define_property(value, STATE_FROZEN_SYMBOL, {
1372+
value: true,
1373+
writable: true,
1374+
enumerable: false
1375+
});
13651376
}
1366-
// Otherwise freeze the object
1367-
object_freeze(value);
13681377
}
13691378
return value;
13701379
}
1380+

0 commit comments

Comments
 (0)