Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8949a3e

Browse files
committed
fix: Fix handling of Symbol and non-enumerable properties in finalization / freeze.Fixes#1096,#1087,#1091 (#1105))
1 parent44363f7 commit8949a3e

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

‎__tests__/base.js‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,6 +2362,22 @@ function testObjectTypes(produce) {
23622362
[customSymbol]:3
23632363
})
23642364
})
2365+
2366+
describe("#1096 / #1087 / proxies",()=>{
2367+
constsym=Symbol()
2368+
2369+
letstate={
2370+
id:1,
2371+
[sym]:{x:2}
2372+
}
2373+
2374+
state=produce(state,draft=>{
2375+
draft.id=2
2376+
draft[sym]
2377+
})
2378+
2379+
expect(state[sym].x).toBe(2)
2380+
})
23652381
}
23662382

23672383
functiontestLiteralTypes(produce){

‎__tests__/frozen.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ function runTests(name) {
219219
state2.ref.state.x++
220220
}).not.toThrow()
221221
expect(state2.ref.state.x).toBe(2)
222+
expect(component.state.x).toBe(2)
222223
})
223224

224225
it("never freezes symbolic fields #590",()=>{

‎src/core/finalize.ts‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,8 @@ function finalize(rootScope: ImmerScope, value: any, path?: PatchPath) {
5858
conststate:ImmerState=value[DRAFT_STATE]
5959
// A plain object, might need freezing, might contain drafts
6060
if(!state){
61-
each(
62-
value,
63-
(key,childValue)=>
64-
finalizeProperty(rootScope,state,value,key,childValue,path),
65-
true// See #590, don't recurse into non-enumerable of non drafted objects
61+
each(value,(key,childValue)=>
62+
finalizeProperty(rootScope,state,value,key,childValue,path)
6663
)
6764
returnvalue
6865
}
@@ -148,8 +145,14 @@ function finalizeProperty(
148145
return
149146
}
150147
finalize(rootScope,childValue)
151-
// immer deep freezes plain objects, so if there is no parent state, we freeze as well
152-
if(!parentState||!parentState.scope_.parent_)
148+
// Immer deep freezes plain objects, so if there is no parent state, we freeze as well
149+
// Per #590, we never freeze symbolic properties. Just to make sure don't accidentally interfere
150+
// with other frameworks.
151+
if(
152+
(!parentState||!parentState.scope_.parent_)&&
153+
typeofprop!=="symbol"&&
154+
Object.prototype.propertyIsEnumerable.call(targetObject,prop)
155+
)
153156
maybeFreeze(rootScope,childValue)
154157
}
155158
}

‎src/utils/common.ts‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,19 @@ export function original(value: Drafted<any>): any {
6060
returnvalue[DRAFT_STATE].base_
6161
}
6262

63+
/**
64+
* Each iterates a map, set or array.
65+
* Or, if any other kind of of object all it's own properties.
66+
* Regardless whether they are enumerable or symbols
67+
*/
6368
exportfunctioneach<TextendsObjectish>(
6469
obj:T,
65-
iter:(key:string|number,value:any,source:T)=>void,
66-
enumerableOnly?:boolean
70+
iter:(key:string|number,value:any,source:T)=>void
6771
):void
6872
exportfunctioneach(obj:any,iter:any){
6973
if(getArchtype(obj)===ArchType.Object){
70-
Object.entries(obj).forEach(([key,value])=>{
71-
iter(key,value,obj)
74+
Reflect.ownKeys(obj).forEach(key=>{
75+
iter(key,obj[key],obj)
7276
})
7377
}else{
7478
obj.forEach((entry:any,index:any)=>iter(index,entry,obj))
@@ -191,7 +195,10 @@ export function freeze<T>(obj: any, deep: boolean = false): T {
191195
obj.set=obj.add=obj.clear=obj.delete=dontMutateFrozenCollectionsasany
192196
}
193197
Object.freeze(obj)
194-
if(deep)each(obj,(_key,value)=>freeze(value,true),true)
198+
if(deep)
199+
// See #590, don't recurse into non-enumerable / Symbol properties when freezing
200+
// So use Object.entries (only string-like, enumerables) instead of each()
201+
Object.entries(obj).forEach(([key,value])=>freeze(value,true))
195202
returnobj
196203
}
197204

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp