@@ -3,39 +3,37 @@ import {
33IProduce ,
44ImmerState ,
55Drafted ,
6- isDraftable ,
7- processResult ,
86Patch ,
97Objectish ,
10- DRAFT_STATE ,
118Draft ,
129PatchListener ,
13- isDraft ,
1410isMap ,
1511isSet ,
1612createProxyProxy ,
1713getPlugin ,
18- die ,
19- enterScope ,
20- revokeScope ,
21- leaveScope ,
22- usePatchesInScope ,
2314getCurrentScope ,
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 {
3028produce :IProduce
3129produceWithPatches :IProduceWithPatches
3230}
3331
34- export type StrictMode = boolean | "class_only" ;
32+ export 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
4038constructor ( config ?:{
4139autoFreeze ?: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 > > (
14776draft :D ,
14877patchListener ?:PatchListener
149- ) :D extends Draft < inferT > ?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 < inferT > ?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 > (