Skip to content

Commit 81fc4b2

Browse files
committed
[object] implement deepFreeze function for yjs/yjs#667
1 parent cafa5ea commit 81fc4b2

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

object.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,27 @@ export const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(ob
113113
* @return {boolean}
114114
*/
115115
export const equalFlat = (a, b) => a === b || (size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && b[key] === val))
116+
117+
/**
118+
* Make an object immutable. This hurts performance and is usually not needed if you perform good
119+
* coding practices.
120+
*/
121+
export const freeze = Object.freeze
122+
123+
/**
124+
* Make an object and all its children immutable.
125+
* This *really* hurts performance and is usually not needed if you perform good coding practices.
126+
*
127+
* @template {any} T
128+
* @param {T} o
129+
* @return {Readonly<T>}
130+
*/
131+
export const deepFreeze = (o) => {
132+
for (const key in o) {
133+
const c = o[key]
134+
if (typeof c === 'object' || typeof c === 'function') {
135+
deepFreeze(o[key])
136+
}
137+
}
138+
return freeze(o)
139+
}

object.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,29 @@ export const testObject = _tc => {
3535
t.assert(object.isEmpty({}))
3636
t.assert(!object.isEmpty({ a: 3 }))
3737
}
38+
39+
/**
40+
* @param {t.TestCase} _tc
41+
*/
42+
export const testFreeze = _tc => {
43+
const o1 = { a: { b: [1, 2, 3] } }
44+
const o2 = [1, 2, { a: 'hi' }]
45+
object.deepFreeze(o1)
46+
object.deepFreeze(o2)
47+
t.fails(() => {
48+
o1.a.b.push(4)
49+
})
50+
t.fails(() => {
51+
o1.a.b = [1]
52+
})
53+
t.fails(() => {
54+
o2.push(4)
55+
})
56+
t.fails(() => {
57+
o2[2] = 42
58+
})
59+
t.fails(() => {
60+
// @ts-ignore-next-line
61+
o2[2].a = 'hello'
62+
})
63+
}

0 commit comments

Comments
 (0)