Skip to content

Commit ed985d4

Browse files
feat: apply Object.freeze in patchState on state in dev mode
1 parent 1f7f740 commit ed985d4

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

modules/signals/spec/signal-state.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,14 @@ describe('signalState', () => {
194194
expect(stateCounter).toBe(3);
195195
expect(userCounter).toBe(1);
196196
}));
197+
198+
it('throws on a mutable change', () => {
199+
const userState = signalState(initialState);
200+
expect(() =>
201+
patchState(userState, (state) => {
202+
state.ngrx = 'mutable change';
203+
return state;
204+
})
205+
).toThrowError("Cannot assign to read only property 'ngrx' of object");
206+
});
197207
});

modules/signals/src/state-source.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
import { SIGNAL } from '@angular/core/primitives/signals';
1111
import { Prettify } from './ts-helpers';
1212

13+
declare const ngDevMode: boolean;
14+
1315
const STATE_WATCHERS = new WeakMap<object, Array<StateWatcher<any>>>();
1416

1517
export const STATE_SOURCE = Symbol('STATE_SOURCE');
@@ -40,7 +42,9 @@ export function patchState<State extends object>(
4042
updaters.reduce(
4143
(nextState: State, updater) => ({
4244
...nextState,
43-
...(typeof updater === 'function' ? updater(nextState) : updater),
45+
...(typeof updater === 'function'
46+
? updater(freezeInDevMode(nextState))
47+
: updater),
4448
}),
4549
currentState
4650
)
@@ -49,6 +53,14 @@ export function patchState<State extends object>(
4953
notifyWatchers(stateSource);
5054
}
5155

56+
function freezeInDevMode<State extends object>(value: State): State {
57+
if (ngDevMode) {
58+
Object.freeze(value);
59+
}
60+
61+
return value;
62+
}
63+
5264
export function getState<State extends object>(
5365
stateSource: StateSource<State>
5466
): State {

0 commit comments

Comments
 (0)