@@ -3,27 +3,25 @@ import {
33 IProduce ,
44 ImmerState ,
55 Drafted ,
6- isDraftable ,
7- processResult ,
86 Patch ,
97 Objectish ,
10- DRAFT_STATE ,
118 Draft ,
129 PatchListener ,
13- isDraft ,
1410 isMap ,
1511 isSet ,
1612 createProxyProxy ,
1713 getPlugin ,
18- die ,
19- enterScope ,
20- revokeScope ,
21- leaveScope ,
22- usePatchesInScope ,
2314 getCurrentScope ,
24- NOTHING ,
25- freeze ,
26- current
15+ DEFAULT_AUTOFREEZE ,
16+ DEFAULT_USE_STRICT_SHALLOW_COPY ,
17+ ImmerContext ,
18+ applyPatchesImpl ,
19+ createDraftImpl ,
20+ finishDraftImpl ,
21+ produceImpl ,
22+ produceWithPatchesImpl ,
23+ setAutoFreezeImpl ,
24+ setUseStrictShallowCopyImpl
2725} from "../internal"
2826
2927interface ProducersFns {
@@ -33,9 +31,9 @@ interface ProducersFns {
3331
3432export type StrictMode = boolean | "class_only" ;
3533
36- export class Immer implements ProducersFns {
37- autoFreeze_ : boolean = true
38- useStrictShallowCopy_ : StrictMode = false
34+ export class Immer implements ProducersFns , ImmerContext {
35+ autoFreeze_ : boolean = DEFAULT_AUTOFREEZE
36+ useStrictShallowCopy_ : StrictMode = DEFAULT_USE_STRICT_SHALLOW_COPY
3937
4038 constructor ( config ?: {
4139 autoFreeze ?: boolean
@@ -66,139 +64,37 @@ export class Immer implements ProducersFns {
6664 * @param {Function } patchListener - optional function that will be called with all the patches produced here
6765 * @returns {any } a new state, or the initial state if nothing was modified
6866 */
69- produce : IProduce = ( base : any , recipe ?: any , patchListener ?: any ) => {
70- // curried invocation
71- if ( typeof base === "function" && typeof recipe !== "function" ) {
72- const defaultBase = recipe
73- recipe = base
67+ produce : IProduce = produceImpl . bind ( this )
7468
75- const self = this
76- return function curriedProduce (
77- this : any ,
78- base = defaultBase ,
79- ...args : any [ ]
80- ) {
81- return self . produce ( base , ( draft : Drafted ) => recipe . call ( this , draft , ...args ) ) // prettier-ignore
82- }
83- }
69+ produceWithPatches : IProduceWithPatches = produceWithPatchesImpl . bind ( this )
8470
85- if ( typeof recipe !== "function" ) die ( 6 )
86- if ( patchListener !== undefined && typeof patchListener !== "function" )
87- die ( 7 )
71+ createDraft = createDraftImpl . bind ( this ) as < T extends Objectish > (
72+ base : T
73+ ) => Draft < T >
8874
89- let result
90-
91- // Only plain objects, arrays, and "immerable classes" are drafted.
92- if ( isDraftable ( base ) ) {
93- const scope = enterScope ( this )
94- const proxy = createProxy ( base , undefined )
95- let hasError = true
96- try {
97- result = recipe ( proxy )
98- hasError = false
99- } finally {
100- // finally instead of catch + rethrow better preserves original stack
101- if ( hasError ) revokeScope ( scope )
102- else leaveScope ( scope )
103- }
104- usePatchesInScope ( scope , patchListener )
105- return processResult ( result , scope )
106- } else if ( ! base || typeof base !== "object" ) {
107- result = recipe ( base )
108- if ( result === undefined ) result = base
109- if ( result === NOTHING ) result = undefined
110- if ( this . autoFreeze_ ) freeze ( result , true )
111- if ( patchListener ) {
112- const p : Patch [ ] = [ ]
113- const ip : Patch [ ] = [ ]
114- getPlugin ( "Patches" ) . generateReplacementPatches_ ( base , result , p , ip )
115- patchListener ( p , ip )
116- }
117- return result
118- } else die ( 1 , base )
119- }
120-
121- produceWithPatches : IProduceWithPatches = ( base : any , recipe ?: any ) : any => {
122- // curried invocation
123- if ( typeof base === "function" ) {
124- return ( state : any , ...args : any [ ] ) =>
125- this . produceWithPatches ( state , ( draft : any ) => base ( draft , ...args ) )
126- }
127-
128- let patches : Patch [ ] , inversePatches : Patch [ ]
129- const result = this . produce ( base , recipe , ( p : Patch [ ] , ip : Patch [ ] ) => {
130- patches = p
131- inversePatches = ip
132- } )
133- return [ result , patches ! , inversePatches ! ]
134- }
135-
136- createDraft < T extends Objectish > ( base : T ) : Draft < T > {
137- if ( ! isDraftable ( base ) ) die ( 8 )
138- if ( isDraft ( base ) ) base = current ( base )
139- const scope = enterScope ( this )
140- const proxy = createProxy ( base , undefined )
141- proxy [ DRAFT_STATE ] . isManual_ = true
142- leaveScope ( scope )
143- return proxy as any
144- }
145-
146- finishDraft < D extends Draft < any > > (
75+ finishDraft = finishDraftImpl . bind ( this ) as < D extends Draft < any > > (
14776 draft : D ,
14877 patchListener ?: PatchListener
149- ) : D extends Draft < infer T > ? T : never {
150- const state : ImmerState = draft && ( draft as any ) [ DRAFT_STATE ]
151- if ( ! state || ! state . isManual_ ) die ( 9 )
152- const { scope_ : scope } = state
153- usePatchesInScope ( scope , patchListener )
154- return processResult ( undefined , scope )
155- }
78+ ) => D extends Draft < infer T > ? T : never
15679
15780 /**
15881 * Pass true to automatically freeze all copies created by Immer.
15982 *
16083 * By default, auto-freezing is enabled.
16184 */
162- setAutoFreeze ( value : boolean ) {
163- this . autoFreeze_ = value
164- }
85+ setAutoFreeze = setAutoFreezeImpl . bind ( this )
16586
16687 /**
16788 * Pass true to enable strict shallow copy.
16889 *
16990 * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
17091 */
171- setUseStrictShallowCopy ( value : StrictMode ) {
172- this . useStrictShallowCopy_ = value
173- }
174-
175- applyPatches < T extends Objectish > ( base : T , patches : readonly Patch [ ] ) : T {
176- // If a patch replaces the entire state, take that replacement as base
177- // before applying patches
178- let i : number
179- for ( i = patches . length - 1 ; i >= 0 ; i -- ) {
180- const patch = patches [ i ]
181- if ( patch . path . length === 0 && patch . op === "replace" ) {
182- base = patch . value
183- break
184- }
185- }
186- // If there was a patch that replaced the entire state, start from the
187- // patch after that.
188- if ( i > - 1 ) {
189- patches = patches . slice ( i + 1 )
190- }
92+ setUseStrictShallowCopy = setUseStrictShallowCopyImpl . bind ( this )
19193
192- const applyPatchesImpl = getPlugin ( "Patches" ) . applyPatches_
193- if ( isDraft ( base ) ) {
194- // N.B: never hits if some patch a replacement, patches are never drafts
195- return applyPatchesImpl ( base , patches )
196- }
197- // Otherwise, produce a copy of the base state.
198- return this . produce ( base , ( draft : Drafted ) =>
199- applyPatchesImpl ( draft , patches )
200- )
201- }
94+ applyPatches = applyPatchesImpl . bind ( this ) as < T extends Objectish > (
95+ base : T ,
96+ patches : readonly Patch [ ]
97+ ) => T
20298}
20399
204100export function createProxy < T extends Objectish > (
0 commit comments