mobx-keystone 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -21
- package/README.md +1 -1
- package/dist/mobx-keystone.esm.js +7198 -6242
- package/dist/mobx-keystone.esm.mjs +7198 -6242
- package/dist/mobx-keystone.umd.js +7217 -6243
- package/dist/types/action/runUnprotected.d.ts +8 -4
- package/dist/types/model/Model.d.ts +5 -0
- package/dist/types/modelShared/modelDecorator.d.ts +1 -1
- package/dist/types/modelShared/prop.d.ts +8 -4
- package/dist/types/snapshot/modelInitialData.d.ts +1 -0
- package/dist/types/tweaker/treeNodeMetadata.d.ts +1 -0
- package/dist/types/types/createCachedTypeCheck.d.ts +1 -0
- package/dist/types/utils/index.d.ts +24 -0
- package/package.json +15 -11
- package/src/action/middleware.ts +5 -18
- package/src/action/mutationBatch.ts +72 -0
- package/src/action/runUnprotected.ts +21 -8
- package/src/action/wrapInAction.ts +45 -15
- package/src/actionMiddlewares/undoMiddleware.ts +19 -13
- package/src/dataModel/BaseDataModel.ts +4 -8
- package/src/deepChange/onDeepChange.ts +246 -16
- package/src/model/BaseModel.ts +4 -12
- package/src/model/Model.ts +5 -0
- package/src/model/newModel.ts +68 -36
- package/src/modelShared/modelDecorator.ts +64 -53
- package/src/modelShared/prop.ts +105 -63
- package/src/modelShared/sharedInternalModel.ts +91 -60
- package/src/parent/core.ts +16 -10
- package/src/parent/coreObjectChildren.ts +219 -21
- package/src/parent/path.ts +6 -5
- package/src/parent/setParent.ts +5 -5
- package/src/patch/emitPatch.ts +102 -20
- package/src/ref/Ref.ts +4 -5
- package/src/ref/core.ts +2 -2
- package/src/snapshot/fromArraySnapshot.ts +11 -2
- package/src/snapshot/fromModelSnapshot.ts +10 -3
- package/src/snapshot/fromPlainObjectSnapshot.ts +18 -7
- package/src/snapshot/fromSnapshot.ts +31 -9
- package/src/snapshot/getSnapshot.ts +8 -3
- package/src/snapshot/internal.ts +243 -82
- package/src/snapshot/modelInitialData.ts +41 -0
- package/src/snapshot/reconcileArraySnapshot.ts +9 -3
- package/src/snapshot/reconcileModelSnapshot.ts +97 -17
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +9 -3
- package/src/treeUtils/draft.ts +7 -8
- package/src/tweaker/core.ts +30 -5
- package/src/tweaker/treeNodeMetadata.ts +38 -0
- package/src/tweaker/tweak.ts +15 -4
- package/src/tweaker/tweakArray.ts +159 -121
- package/src/tweaker/tweakFrozen.ts +2 -2
- package/src/tweaker/tweakModel.ts +2 -2
- package/src/tweaker/tweakPlainObject.ts +117 -124
- package/src/tweaker/typeChecking.ts +10 -1
- package/src/types/TypeChecker.ts +261 -15
- package/src/types/arrayBased/typesArray.ts +38 -40
- package/src/types/arrayBased/typesTuple.ts +51 -34
- package/src/types/createCachedTypeCheck.ts +181 -0
- package/src/types/objectBased/typesArraySet.ts +42 -32
- package/src/types/objectBased/typesDataModelData.ts +18 -11
- package/src/types/objectBased/typesModel.ts +1 -1
- package/src/types/objectBased/typesObject.ts +57 -28
- package/src/types/objectBased/typesObjectMap.ts +51 -40
- package/src/types/objectBased/typesRecord.ts +59 -39
- package/src/types/objectBased/typesRef.ts +1 -1
- package/src/types/primitiveBased/typesPrimitive.ts +9 -9
- package/src/types/tProp.ts +80 -44
- package/src/types/utility/typesOr.ts +35 -24
- package/src/types/utility/typesRefinement.ts +21 -8
- package/src/types/utility/typesSkipCheck.ts +21 -8
- package/src/types/utility/typesTag.ts +21 -9
- package/src/types/utility/typesUnchecked.ts +2 -3
- package/src/utils/ModelPool.ts +34 -19
- package/src/utils/errorDiagnostics.ts +60 -18
- package/src/utils/index.ts +142 -9
- package/src/types/createPerEntryCachedCheck.ts +0 -166
- /package/dist/types/{types/createPerEntryCachedCheck.d.ts → action/mutationBatch.d.ts} +0 -0
|
@@ -7,29 +7,35 @@ import {
|
|
|
7
7
|
observe,
|
|
8
8
|
} from "mobx"
|
|
9
9
|
import { assertCanWrite } from "../action/protection"
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
emitObjectAddDeepChange,
|
|
12
|
+
emitObjectRemoveDeepChange,
|
|
13
|
+
emitObjectUpdateDeepChange,
|
|
14
|
+
} from "../deepChange/onDeepChange"
|
|
11
15
|
import type { AnyModel } from "../model/BaseModel"
|
|
12
16
|
import { modelTypeKey } from "../model/metadata"
|
|
13
17
|
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
14
18
|
import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
|
|
15
19
|
import { dataToModelNode } from "../parent/core"
|
|
16
20
|
import type { ParentPath } from "../parent/path"
|
|
17
|
-
import type { Path } from "../parent/pathTypes"
|
|
18
21
|
import { setParent } from "../parent/setParent"
|
|
19
|
-
import { InternalPatchRecorder } from "../patch/emitPatch"
|
|
22
|
+
import { hasPatchListenersFor, InternalPatchRecorder } from "../patch/emitPatch"
|
|
20
23
|
import {
|
|
24
|
+
flushInternalSnapshot,
|
|
21
25
|
freezeInternalSnapshot,
|
|
22
26
|
getInternalSnapshot,
|
|
23
27
|
type SnapshotTransformFn,
|
|
24
28
|
setNewInternalSnapshot,
|
|
25
29
|
updateInternalSnapshot,
|
|
26
30
|
} from "../snapshot/internal"
|
|
27
|
-
import {
|
|
31
|
+
import { takeModelInitialDataSnapshot } from "../snapshot/modelInitialData"
|
|
32
|
+
import { failure, isPlainObject, isPrimitive, setProtoProp } from "../utils"
|
|
28
33
|
import { setIfDifferent } from "../utils/setIfDifferent"
|
|
29
|
-
import { runningWithoutSnapshotOrPatches,
|
|
34
|
+
import { runningWithoutSnapshotOrPatches, setTweakedObjectUntweakers } from "./core"
|
|
30
35
|
import { TweakerPriority } from "./TweakerPriority"
|
|
36
|
+
import { markAsTweakedObject } from "./treeNodeMetadata"
|
|
31
37
|
import { registerTweaker, tweak } from "./tweak"
|
|
32
|
-
import { runTypeCheckingAfterChange } from "./typeChecking"
|
|
38
|
+
import { isTypeCheckingAfterChangeEnabled, runTypeCheckingAfterChange } from "./typeChecking"
|
|
33
39
|
|
|
34
40
|
/**
|
|
35
41
|
* @internal
|
|
@@ -42,19 +48,14 @@ export function tweakPlainObject<T extends Record<string, any>>(
|
|
|
42
48
|
isDataObject: boolean
|
|
43
49
|
): T {
|
|
44
50
|
const originalObj: Record<string, any> = value
|
|
45
|
-
const
|
|
51
|
+
const originalIsObservableObject = isObservableObject(originalObj)
|
|
52
|
+
const tweakedObj = originalIsObservableObject
|
|
46
53
|
? originalObj
|
|
47
54
|
: observable.object({}, undefined, observableOptions)
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const untweak = () => {
|
|
53
|
-
interceptDisposer()
|
|
54
|
-
observeDisposer()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
tweakedObjects.set(tweakedObj, untweak)
|
|
56
|
+
// Mark it as tweaked before processing children. The cleanup functions are
|
|
57
|
+
// installed after the MobX handlers have been registered.
|
|
58
|
+
markAsTweakedObject(tweakedObj)
|
|
58
59
|
setParent(
|
|
59
60
|
tweakedObj, // value
|
|
60
61
|
parentPath,
|
|
@@ -64,20 +65,28 @@ export function tweakPlainObject<T extends Record<string, any>>(
|
|
|
64
65
|
false // cloneIfApplicable
|
|
65
66
|
)
|
|
66
67
|
|
|
67
|
-
const
|
|
68
|
+
const initialDataSnapshot =
|
|
69
|
+
isDataObject && snapshotModelType ? takeModelInitialDataSnapshot(tweakedObj) : undefined
|
|
70
|
+
const reuseInitialDataSnapshot =
|
|
71
|
+
!!initialDataSnapshot?.reusable && initialDataSnapshot.allValuesPrimitive
|
|
72
|
+
const untransformedSn: any = reuseInitialDataSnapshot ? initialDataSnapshot.snapshot : {}
|
|
68
73
|
|
|
69
74
|
// substitute initial values by tweaked values
|
|
70
|
-
const originalObjKeys = Object.keys(originalObj)
|
|
75
|
+
const originalObjKeys = reuseInitialDataSnapshot ? [] : Object.keys(originalObj)
|
|
71
76
|
const originalObjKeysLen = originalObjKeys.length
|
|
72
77
|
for (let i = 0; i < originalObjKeysLen; i++) {
|
|
73
78
|
const k = originalObjKeys[i]
|
|
74
79
|
const v = originalObj[k]
|
|
75
80
|
|
|
76
81
|
if (isPrimitive(v)) {
|
|
77
|
-
if (!doNotTweakChildren) {
|
|
82
|
+
if (!doNotTweakChildren && !originalIsObservableObject) {
|
|
78
83
|
setIfDifferent(tweakedObj, k, v)
|
|
79
84
|
}
|
|
80
|
-
|
|
85
|
+
if (k === "__proto__") {
|
|
86
|
+
setProtoProp(untransformedSn, v)
|
|
87
|
+
} else {
|
|
88
|
+
untransformedSn[k] = v
|
|
89
|
+
}
|
|
81
90
|
} else {
|
|
82
91
|
const path = { parent: tweakedObj, path: k }
|
|
83
92
|
|
|
@@ -98,13 +107,17 @@ export function tweakPlainObject<T extends Record<string, any>>(
|
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
const valueSn = getInternalSnapshot(tweakedValue)!
|
|
101
|
-
|
|
110
|
+
if (k === "__proto__") {
|
|
111
|
+
setProtoProp(untransformedSn, valueSn.transformed)
|
|
112
|
+
} else {
|
|
113
|
+
untransformedSn[k] = valueSn.transformed
|
|
114
|
+
}
|
|
102
115
|
}
|
|
103
116
|
}
|
|
104
117
|
|
|
105
118
|
let transformFn: SnapshotTransformFn | undefined
|
|
106
119
|
if (snapshotModelType) {
|
|
107
|
-
|
|
120
|
+
untransformedSn[modelTypeKey] = snapshotModelType
|
|
108
121
|
|
|
109
122
|
const modelInfo = getModelInfoForName(snapshotModelType)
|
|
110
123
|
if (!modelInfo) {
|
|
@@ -123,8 +136,9 @@ export function tweakPlainObject<T extends Record<string, any>>(
|
|
|
123
136
|
transformFn
|
|
124
137
|
)
|
|
125
138
|
|
|
126
|
-
interceptDisposer = intercept(tweakedObj, interceptObjectMutation)
|
|
127
|
-
observeDisposer = observe(tweakedObj, objectDidChange)
|
|
139
|
+
const interceptDisposer = intercept(tweakedObj, interceptObjectMutation)
|
|
140
|
+
const observeDisposer = observe(tweakedObj, objectDidChange)
|
|
141
|
+
setTweakedObjectUntweakers(tweakedObj, interceptDisposer, observeDisposer)
|
|
128
142
|
|
|
129
143
|
return tweakedObj as any
|
|
130
144
|
}
|
|
@@ -134,7 +148,11 @@ const observableOptions = {
|
|
|
134
148
|
}
|
|
135
149
|
|
|
136
150
|
function mutateSet(k: PropertyKey, v: unknown, sn: Record<PropertyKey, unknown>) {
|
|
137
|
-
|
|
151
|
+
if (k === "__proto__") {
|
|
152
|
+
setProtoProp(sn, v)
|
|
153
|
+
} else {
|
|
154
|
+
sn[k] = v
|
|
155
|
+
}
|
|
138
156
|
}
|
|
139
157
|
|
|
140
158
|
function mutateDelete(k: PropertyKey, sn: Record<PropertyKey, unknown>) {
|
|
@@ -143,8 +161,6 @@ function mutateDelete(k: PropertyKey, sn: Record<PropertyKey, unknown>) {
|
|
|
143
161
|
|
|
144
162
|
const patchRecorder = new InternalPatchRecorder()
|
|
145
163
|
|
|
146
|
-
const emptyPath: Path = Object.freeze([])
|
|
147
|
-
|
|
148
164
|
function objectDidChange(change: IObjectDidChange): void {
|
|
149
165
|
if (typeof change.name !== "string") {
|
|
150
166
|
throw failure("change.name is not a string")
|
|
@@ -152,99 +168,88 @@ function objectDidChange(change: IObjectDidChange): void {
|
|
|
152
168
|
|
|
153
169
|
const obj = change.object
|
|
154
170
|
const actualNode = dataToModelNode(obj)
|
|
155
|
-
const oldUntransformedSn = getInternalSnapshot(actualNode)!.untransformed
|
|
156
171
|
|
|
157
172
|
patchRecorder.reset()
|
|
158
173
|
|
|
159
|
-
let mutate: ((sn: any) => void) | undefined
|
|
160
|
-
|
|
161
174
|
switch (change.type) {
|
|
162
|
-
case "add":
|
|
163
|
-
|
|
164
|
-
// Emit deep change for add
|
|
165
|
-
emitDeepChange(actualNode, {
|
|
166
|
-
type: DeepChangeType.ObjectAdd,
|
|
167
|
-
target: obj as object,
|
|
168
|
-
path: emptyPath,
|
|
169
|
-
key: change.name,
|
|
170
|
-
newValue: change.newValue,
|
|
171
|
-
isInit: getIsInInitPhase(),
|
|
172
|
-
})
|
|
175
|
+
case "add":
|
|
176
|
+
emitObjectAddDeepChange(actualNode, obj, change.name, change.newValue)
|
|
173
177
|
break
|
|
174
|
-
}
|
|
175
178
|
|
|
176
|
-
case "update":
|
|
177
|
-
|
|
178
|
-
// Emit deep change for update
|
|
179
|
-
emitDeepChange(actualNode, {
|
|
180
|
-
type: DeepChangeType.ObjectUpdate,
|
|
181
|
-
target: obj as object,
|
|
182
|
-
path: emptyPath,
|
|
183
|
-
key: change.name,
|
|
184
|
-
newValue: change.newValue,
|
|
185
|
-
oldValue: change.oldValue,
|
|
186
|
-
isInit: getIsInInitPhase(),
|
|
187
|
-
})
|
|
179
|
+
case "update":
|
|
180
|
+
emitObjectUpdateDeepChange(actualNode, obj, change.name, change.newValue, change.oldValue)
|
|
188
181
|
break
|
|
189
|
-
}
|
|
190
182
|
|
|
191
|
-
case "remove":
|
|
192
|
-
|
|
193
|
-
// Emit deep change for remove
|
|
194
|
-
emitDeepChange(actualNode, {
|
|
195
|
-
type: DeepChangeType.ObjectRemove,
|
|
196
|
-
target: obj as object,
|
|
197
|
-
path: emptyPath,
|
|
198
|
-
key: change.name,
|
|
199
|
-
oldValue: change.oldValue,
|
|
200
|
-
isInit: getIsInInitPhase(),
|
|
201
|
-
})
|
|
183
|
+
case "remove":
|
|
184
|
+
emitObjectRemoveDeepChange(actualNode, obj, change.name, change.oldValue)
|
|
202
185
|
break
|
|
203
|
-
}
|
|
204
186
|
|
|
205
187
|
default:
|
|
206
188
|
throw failure("assertion error: unsupported object change type")
|
|
207
189
|
}
|
|
208
190
|
|
|
209
|
-
|
|
191
|
+
if (runningWithoutSnapshotOrPatches) {
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const oldUntransformedSn = getInternalSnapshot(actualNode)!.untransformed
|
|
196
|
+
const shouldEmitPatches = hasPatchListenersFor(actualNode)
|
|
197
|
+
const shouldBuildInversePatches = shouldEmitPatches || isTypeCheckingAfterChangeEnabled()
|
|
210
198
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
199
|
+
let mutate: ((sn: any) => void) | undefined
|
|
200
|
+
switch (change.type) {
|
|
201
|
+
case "add":
|
|
202
|
+
case "update":
|
|
203
|
+
mutate = objectDidChangeAddOrUpdate(
|
|
204
|
+
change,
|
|
205
|
+
oldUntransformedSn,
|
|
206
|
+
shouldEmitPatches,
|
|
207
|
+
shouldBuildInversePatches
|
|
208
|
+
)
|
|
209
|
+
break
|
|
210
|
+
case "remove":
|
|
211
|
+
mutate = objectDidChangeRemove(
|
|
212
|
+
change,
|
|
213
|
+
oldUntransformedSn,
|
|
214
|
+
shouldEmitPatches,
|
|
215
|
+
shouldBuildInversePatches
|
|
216
|
+
)
|
|
217
|
+
break
|
|
218
|
+
default:
|
|
219
|
+
throw failure("assertion error: unsupported object change type")
|
|
214
220
|
}
|
|
221
|
+
|
|
222
|
+
runTypeCheckingAfterChange(obj, patchRecorder)
|
|
223
|
+
updateInternalSnapshot(actualNode, mutate)
|
|
224
|
+
patchRecorder.emit(actualNode)
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
function objectDidChangeRemove(
|
|
218
228
|
change: IObjectDidChange & { type: "remove" },
|
|
219
|
-
oldUntransformedSn: any
|
|
229
|
+
oldUntransformedSn: any,
|
|
230
|
+
shouldEmitPatches: boolean,
|
|
231
|
+
shouldBuildInversePatches: boolean
|
|
220
232
|
) {
|
|
221
233
|
const k = change.name
|
|
222
234
|
const oldVal = oldUntransformedSn[k]
|
|
223
235
|
const mutate = mutateDelete.bind(undefined, k)
|
|
224
236
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
],
|
|
234
|
-
[
|
|
235
|
-
{
|
|
236
|
-
op: "add",
|
|
237
|
-
path,
|
|
238
|
-
value: freezeInternalSnapshot(oldVal),
|
|
239
|
-
},
|
|
240
|
-
]
|
|
241
|
-
)
|
|
237
|
+
if (shouldEmitPatches || shouldBuildInversePatches) {
|
|
238
|
+
const path = [k as string]
|
|
239
|
+
const patches = shouldEmitPatches ? [{ op: "remove" as const, path }] : undefined
|
|
240
|
+
const invPatches = shouldBuildInversePatches
|
|
241
|
+
? [{ op: "add" as const, path, value: freezeInternalSnapshot(oldVal) }]
|
|
242
|
+
: undefined
|
|
243
|
+
patchRecorder.record(patches, invPatches)
|
|
244
|
+
}
|
|
242
245
|
return mutate
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
function objectDidChangeAddOrUpdate(
|
|
246
249
|
change: IObjectWillChange & { type: "add" | "update" },
|
|
247
|
-
oldUntransformedSn: any
|
|
250
|
+
oldUntransformedSn: any,
|
|
251
|
+
shouldEmitPatches: boolean,
|
|
252
|
+
shouldBuildInversePatches: boolean
|
|
248
253
|
) {
|
|
249
254
|
const k = change.name
|
|
250
255
|
const val = change.newValue
|
|
@@ -261,40 +266,23 @@ function objectDidChangeAddOrUpdate(
|
|
|
261
266
|
|
|
262
267
|
const mutate = mutateSet.bind(undefined, k, newVal)
|
|
263
268
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
} else {
|
|
282
|
-
patchRecorder.record(
|
|
283
|
-
[
|
|
284
|
-
{
|
|
285
|
-
op: "replace",
|
|
286
|
-
path,
|
|
287
|
-
value: freezeInternalSnapshot(newVal),
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
[
|
|
291
|
-
{
|
|
292
|
-
op: "replace",
|
|
293
|
-
path,
|
|
294
|
-
value: freezeInternalSnapshot(oldVal),
|
|
295
|
-
},
|
|
296
|
-
]
|
|
297
|
-
)
|
|
269
|
+
if (shouldEmitPatches || shouldBuildInversePatches) {
|
|
270
|
+
const path = [k as string]
|
|
271
|
+
if (change.type === "add") {
|
|
272
|
+
const patches = shouldEmitPatches
|
|
273
|
+
? [{ op: "add" as const, path, value: freezeInternalSnapshot(newVal) }]
|
|
274
|
+
: undefined
|
|
275
|
+
const invPatches = shouldBuildInversePatches ? [{ op: "remove" as const, path }] : undefined
|
|
276
|
+
patchRecorder.record(patches, invPatches)
|
|
277
|
+
} else {
|
|
278
|
+
const patches = shouldEmitPatches
|
|
279
|
+
? [{ op: "replace" as const, path, value: freezeInternalSnapshot(newVal) }]
|
|
280
|
+
: undefined
|
|
281
|
+
const invPatches = shouldBuildInversePatches
|
|
282
|
+
? [{ op: "replace" as const, path, value: freezeInternalSnapshot(oldVal) }]
|
|
283
|
+
: undefined
|
|
284
|
+
patchRecorder.record(patches, invPatches)
|
|
285
|
+
}
|
|
298
286
|
}
|
|
299
287
|
|
|
300
288
|
return mutate
|
|
@@ -307,6 +295,11 @@ function interceptObjectMutation(change: IObjectWillChange) {
|
|
|
307
295
|
throw failure("symbol properties are not supported")
|
|
308
296
|
}
|
|
309
297
|
|
|
298
|
+
// This must happen before detach/reparent work below. It keeps the old value
|
|
299
|
+
// available for inverse patches and folds a departing dirty child into its
|
|
300
|
+
// parent snapshot while its parent path still exists.
|
|
301
|
+
flushInternalSnapshot(dataToModelNode(change.object), false)
|
|
302
|
+
|
|
310
303
|
switch (change.type) {
|
|
311
304
|
case "add":
|
|
312
305
|
change.newValue = tweak(change.newValue, {
|
|
@@ -18,6 +18,15 @@ import { isTypeCheckingAllowed } from "./withoutTypeChecking"
|
|
|
18
18
|
// still be invalid, causing another rollback attempt).
|
|
19
19
|
let isRollingBackTypeCheckFailure = false
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function isTypeCheckingAfterChangeEnabled(): boolean {
|
|
25
|
+
return (
|
|
26
|
+
isTypeCheckingAllowed() && isModelAutoTypeCheckingEnabled() && !isRollingBackTypeCheckFailure
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
21
30
|
function isModelWithTypeChecker(obj: object): obj is AnyModel {
|
|
22
31
|
return isModel(obj) && !!getModelMetadata(obj).dataType
|
|
23
32
|
}
|
|
@@ -68,7 +77,7 @@ export function runTypeCheckingAfterChange(
|
|
|
68
77
|
return
|
|
69
78
|
}
|
|
70
79
|
|
|
71
|
-
if (patchRecorder && patchRecorder.
|
|
80
|
+
if (patchRecorder && !patchRecorder.hasChanges) {
|
|
72
81
|
// No patches means no effective change.
|
|
73
82
|
return
|
|
74
83
|
}
|