@@ -721,3 +721,79 @@ test('CustomMap', () => {
721721 expect ( newState . getIdentity ( ) ) . toBe ( 'CustomMap' ) ;
722722 }
723723} ) ;
724+
725+ test ( 'Unexpected undefined not assigned' , ( ) => {
726+ {
727+ // #1160 https://github.com/immerjs/immer/issues/1160
728+ const proto = { [ immerable ] : true , name : undefined } ;
729+ const foo = Object . create ( proto ) ;
730+
731+ // Initial state: foo should not have own property 'name'
732+ expect ( Object . prototype . hasOwnProperty . call ( foo , 'name' ) ) . toBe ( false ) ;
733+
734+ enablePatches ( ) ;
735+ // @ts -ignore
736+ const [ foo_next , patches , _ ] = produceWithPatches ( foo , ( x ) => {
737+ x . name = undefined ;
738+ } ) ;
739+
740+ // Immer should produce empty patches when setting undefined
741+ expect ( patches ) . toEqual ( [ ] ) ;
742+
743+ // After immer produce, foo should still not have own property 'name'
744+ expect ( Object . prototype . hasOwnProperty . call ( foo , 'name' ) ) . toBe ( false ) ;
745+ // foo_next should also not have own property 'name'
746+ expect ( Object . prototype . hasOwnProperty . call ( foo_next , 'name' ) ) . toBe ( false ) ;
747+
748+ // Manually assigning undefined should create own property
749+ foo . name = undefined ;
750+ expect ( Object . prototype . hasOwnProperty . call ( foo , 'name' ) ) . toBe ( true ) ;
751+
752+ // [hasOwnProp] foo: false
753+ // [immer] produce foo_next from immer
754+ // [immer] foo_next patches: [
755+ // {
756+ // op: "add",
757+ // path: [ "name" ],
758+ // value: undefined,
759+ // }
760+ // ]
761+ // [hasOwnProp] foo: false
762+ // [hasOwnProp] foo_next: true
763+ // [vanilla] assign name manually
764+ // [hasOwnProp] foo: true
765+ }
766+ {
767+ const immerable = Symbol ( ) ;
768+ const proto = { [ immerable ] : true , name : undefined } ;
769+ const foo = Object . create ( proto ) ;
770+
771+ const [ foo_next , patches , _ ] = create (
772+ foo ,
773+ ( x ) => {
774+ x . name = undefined ;
775+ } ,
776+ {
777+ enablePatches : true ,
778+ mark : ( target ) => {
779+ if ( target && target [ immerable ] ) {
780+ return 'immutable' ;
781+ }
782+ } ,
783+ }
784+ ) ;
785+
786+ expect ( patches ) . toEqual ( [
787+ {
788+ op : 'add' ,
789+ path : [ 'name' ] ,
790+ value : undefined ,
791+ } ,
792+ ] ) ;
793+ expect ( Object . prototype . hasOwnProperty . call ( foo , 'name' ) ) . toBe ( false ) ;
794+ expect ( Object . prototype . hasOwnProperty . call ( foo_next , 'name' ) ) . toBe ( true ) ;
795+
796+ foo . name = undefined ;
797+ expect ( Object . prototype . hasOwnProperty . call ( foo , 'name' ) ) . toBe ( true ) ;
798+ }
799+ } ) ;
0 commit comments