mobx-keystone 1.22.0 → 1.23.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 +7 -0
- package/dist/mobx-keystone.esm.js +6702 -5797
- package/dist/mobx-keystone.esm.mjs +6702 -5797
- package/dist/mobx-keystone.umd.js +6718 -5798
- package/dist/types/action/runUnprotected.d.ts +8 -4
- package/dist/types/model/Model.d.ts +5 -0
- 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/package.json +11 -10
- 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/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/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/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/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 +114 -122
- 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 +9 -7
- package/src/types/createPerEntryCachedCheck.ts +0 -166
- /package/dist/types/{types/createPerEntryCachedCheck.d.ts → action/mutationBatch.d.ts} +0 -0
package/src/utils/ModelPool.ts
CHANGED
|
@@ -4,28 +4,27 @@ import { modelIdKey, modelTypeKey } from "../model/metadata"
|
|
|
4
4
|
import { getSnapshotModelType, isModel } from "../model/utils"
|
|
5
5
|
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
6
6
|
import { getModelInfoForName } from "../modelShared/modelInfo"
|
|
7
|
-
import {
|
|
7
|
+
import { dataToModelNode } from "../parent/core"
|
|
8
8
|
import {
|
|
9
9
|
getDeepObjectChildren,
|
|
10
10
|
registerDeepObjectChildrenExtension,
|
|
11
11
|
} from "../parent/coreObjectChildren"
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
type ModelsById = Map<string, AnyModel>
|
|
14
|
+
type ModelsByTypeAndId = Map<string, ModelsById>
|
|
16
15
|
|
|
17
16
|
export class ModelPool {
|
|
18
|
-
private pool: ReadonlyMap<string, AnyModel
|
|
17
|
+
private pool: ReadonlyMap<string, ReadonlyMap<string, AnyModel>>
|
|
19
18
|
|
|
20
19
|
constructor(root: object) {
|
|
21
20
|
// make sure we don't use the sub-data $ object
|
|
22
|
-
root =
|
|
21
|
+
root = dataToModelNode(root)
|
|
23
22
|
|
|
24
23
|
this.pool = getDeepChildrenModels(getDeepObjectChildren(root))
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
findModelByTypeAndId(modelType: string, modelId: string | undefined): AnyModel | undefined {
|
|
28
|
-
return modelId ? this.pool.get(
|
|
27
|
+
return modelId ? this.pool.get(modelType)?.get(modelId) : undefined
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
findModelForSnapshot(sn: any): AnyModel | undefined {
|
|
@@ -43,17 +42,33 @@ export class ModelPool {
|
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
type GetDeepChildrenModels = (data: ReturnType<typeof getDeepObjectChildren>) => ModelsByTypeAndId
|
|
46
|
+
|
|
47
|
+
let getDeepChildrenModels: GetDeepChildrenModels = (data) => {
|
|
48
|
+
// Register on first use to keep ModelPool out of the coreObjectChildren
|
|
49
|
+
// module-initialization cycle. The extension getter backfills its index from
|
|
50
|
+
// data.deep, so registering after a deep-children set already exists is safe.
|
|
51
|
+
const getRegisteredDeepChildrenModels = registerDeepObjectChildrenExtension<ModelsByTypeAndId>({
|
|
52
|
+
initData() {
|
|
53
|
+
return new Map()
|
|
54
|
+
},
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
addNode(node, extensionData) {
|
|
57
|
+
if (isModel(node)) {
|
|
58
|
+
const id = node[modelIdKey]
|
|
59
|
+
if (id) {
|
|
60
|
+
const modelType = node[modelTypeKey]
|
|
61
|
+
let modelsById = extensionData.get(modelType)
|
|
62
|
+
if (!modelsById) {
|
|
63
|
+
modelsById = new Map()
|
|
64
|
+
extensionData.set(modelType, modelsById)
|
|
65
|
+
}
|
|
66
|
+
modelsById.set(id, node)
|
|
67
|
+
}
|
|
56
68
|
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
getDeepChildrenModels = getRegisteredDeepChildrenModels
|
|
73
|
+
return getRegisteredDeepChildrenModels(data)
|
|
74
|
+
}
|
|
@@ -1,13 +1,59 @@
|
|
|
1
1
|
import type { Path, PathElement, WritablePath } from "../parent/pathTypes"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export class ErrorDiagnosticsContext {
|
|
7
|
+
private readonly path: WritablePath = []
|
|
8
|
+
private readonly modelTrailTypes: string[] = []
|
|
9
|
+
private readonly modelTrailIds: (string | undefined)[] = []
|
|
10
|
+
|
|
11
|
+
pushPath(segment: PathElement): void {
|
|
12
|
+
this.path.push(segment)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
popPath(): void {
|
|
16
|
+
this.path.pop()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getPathLength(): number {
|
|
20
|
+
return this.path.length
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
truncatePath(length: number): void {
|
|
24
|
+
this.path.length = length
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pushModelTrail(modelType: string, modelId: string | undefined): void {
|
|
28
|
+
this.modelTrailTypes.push(modelType)
|
|
29
|
+
this.modelTrailIds.push(modelId)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
popModelTrail(): void {
|
|
33
|
+
this.modelTrailTypes.pop()
|
|
34
|
+
this.modelTrailIds.pop()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getPathSnapshot(): Path {
|
|
38
|
+
return [...this.path]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getModelTrailSnapshot(): readonly string[] | undefined {
|
|
42
|
+
if (this.modelTrailTypes.length <= 0) {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
return this.modelTrailTypes.map((modelType, index) =>
|
|
46
|
+
formatErrorModelTrailEntry(modelType, this.modelTrailIds[index])
|
|
47
|
+
)
|
|
48
|
+
}
|
|
6
49
|
}
|
|
7
50
|
|
|
8
51
|
const errorDiagnosticsContextStack: ErrorDiagnosticsContext[] = []
|
|
9
52
|
|
|
10
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
export function getCurrentErrorDiagnosticsContext(): ErrorDiagnosticsContext | undefined {
|
|
11
57
|
return errorDiagnosticsContextStack.length > 0
|
|
12
58
|
? errorDiagnosticsContextStack[errorDiagnosticsContextStack.length - 1]
|
|
13
59
|
: undefined
|
|
@@ -22,10 +68,7 @@ export function runWithErrorDiagnosticsContext<T>(fn: () => T): T {
|
|
|
22
68
|
return fn()
|
|
23
69
|
}
|
|
24
70
|
|
|
25
|
-
const ctx
|
|
26
|
-
path: [],
|
|
27
|
-
modelTrail: [],
|
|
28
|
-
}
|
|
71
|
+
const ctx = new ErrorDiagnosticsContext()
|
|
29
72
|
errorDiagnosticsContextStack.push(ctx)
|
|
30
73
|
try {
|
|
31
74
|
return fn()
|
|
@@ -43,11 +86,11 @@ export function withErrorPathSegment<T>(segment: PathElement, fn: () => T): T {
|
|
|
43
86
|
return fn()
|
|
44
87
|
}
|
|
45
88
|
|
|
46
|
-
ctx.
|
|
89
|
+
ctx.pushPath(segment)
|
|
47
90
|
try {
|
|
48
91
|
return fn()
|
|
49
92
|
} finally {
|
|
50
|
-
ctx.
|
|
93
|
+
ctx.popPath()
|
|
51
94
|
}
|
|
52
95
|
}
|
|
53
96
|
|
|
@@ -64,16 +107,16 @@ export function withErrorPathSegments<T>(segments: readonly PathElement[], fn: (
|
|
|
64
107
|
return fn()
|
|
65
108
|
}
|
|
66
109
|
|
|
67
|
-
const initialLen = ctx.
|
|
110
|
+
const initialLen = ctx.getPathLength()
|
|
68
111
|
const segmentsLen = segments.length
|
|
69
112
|
for (let i = 0; i < segmentsLen; i++) {
|
|
70
|
-
ctx.
|
|
113
|
+
ctx.pushPath(segments[i]!)
|
|
71
114
|
}
|
|
72
115
|
|
|
73
116
|
try {
|
|
74
117
|
return fn()
|
|
75
118
|
} finally {
|
|
76
|
-
ctx.
|
|
119
|
+
ctx.truncatePath(initialLen)
|
|
77
120
|
}
|
|
78
121
|
}
|
|
79
122
|
|
|
@@ -112,12 +155,11 @@ export function withErrorModelTrailEntry<T>(
|
|
|
112
155
|
return fn()
|
|
113
156
|
}
|
|
114
157
|
|
|
115
|
-
|
|
116
|
-
ctx.modelTrail.push(entry)
|
|
158
|
+
ctx.pushModelTrail(modelType, modelId)
|
|
117
159
|
try {
|
|
118
160
|
return fn()
|
|
119
161
|
} finally {
|
|
120
|
-
ctx.
|
|
162
|
+
ctx.popModelTrail()
|
|
121
163
|
}
|
|
122
164
|
}
|
|
123
165
|
|
|
@@ -126,7 +168,7 @@ export function withErrorModelTrailEntry<T>(
|
|
|
126
168
|
*/
|
|
127
169
|
export function getErrorPathSnapshot(): Path | undefined {
|
|
128
170
|
const ctx = getCurrentErrorDiagnosticsContext()
|
|
129
|
-
return ctx
|
|
171
|
+
return ctx?.getPathSnapshot()
|
|
130
172
|
}
|
|
131
173
|
|
|
132
174
|
/**
|
|
@@ -134,7 +176,7 @@ export function getErrorPathSnapshot(): Path | undefined {
|
|
|
134
176
|
*/
|
|
135
177
|
export function getErrorModelTrailSnapshot(): readonly string[] | undefined {
|
|
136
178
|
const ctx = getCurrentErrorDiagnosticsContext()
|
|
137
|
-
return ctx
|
|
179
|
+
return ctx?.getModelTrailSnapshot()
|
|
138
180
|
}
|
|
139
181
|
|
|
140
182
|
/**
|
package/src/utils/index.ts
CHANGED
|
@@ -109,12 +109,7 @@ export let hasOwnProp: (object: object, propName: PropertyKey) => boolean = (
|
|
|
109
109
|
/**
|
|
110
110
|
* @internal
|
|
111
111
|
*/
|
|
112
|
-
export function
|
|
113
|
-
if (propName !== "__proto__") {
|
|
114
|
-
target[propName] = value
|
|
115
|
-
return
|
|
116
|
-
}
|
|
117
|
-
|
|
112
|
+
export function setProtoProp(target: object, value: unknown): void {
|
|
118
113
|
Object.defineProperty(target, "__proto__", {
|
|
119
114
|
enumerable: true,
|
|
120
115
|
writable: true,
|
|
@@ -136,7 +131,12 @@ export function copyOwnEnumerableProps<TTarget extends Record<string, any>>(
|
|
|
136
131
|
for (let i = 0; i < len; i++) {
|
|
137
132
|
const key = keys[i]
|
|
138
133
|
const value = source[key]
|
|
139
|
-
|
|
134
|
+
const mappedValue = mapValue ? mapValue(value, key) : value
|
|
135
|
+
if (key === "__proto__") {
|
|
136
|
+
setProtoProp(target, mappedValue)
|
|
137
|
+
} else {
|
|
138
|
+
;(target as Record<PropertyKey, unknown>)[key] = mappedValue
|
|
139
|
+
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
return target
|
|
@@ -432,6 +432,8 @@ export function propNameToSetterName(propName: string): string {
|
|
|
432
432
|
export function getMobxVersion(): number {
|
|
433
433
|
if (mobx6.makeObservable!) {
|
|
434
434
|
return 6
|
|
435
|
+
} else if ("extendShallowObservable" in mobx) {
|
|
436
|
+
return 4
|
|
435
437
|
} else {
|
|
436
438
|
return 5
|
|
437
439
|
}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computed,
|
|
3
|
-
type IArrayDidChange,
|
|
4
|
-
type IComputedValue,
|
|
5
|
-
type IObjectDidChange,
|
|
6
|
-
observe,
|
|
7
|
-
} from "mobx"
|
|
8
|
-
import type { Path } from "../parent/pathTypes"
|
|
9
|
-
import { isTweakedObject } from "../tweaker/core"
|
|
10
|
-
import type { TypeCheckError } from "./TypeCheckError"
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @internal
|
|
14
|
-
*
|
|
15
|
-
* Per-entry cache map type used by `createPerEntryCachedCheck`.
|
|
16
|
-
*/
|
|
17
|
-
export type PerEntryCache = Map<PropertyKey, IComputedValue<TypeCheckError | null>>
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @internal
|
|
21
|
-
*
|
|
22
|
-
* Callback that sets up reactive pruning of stale per-entry cache entries.
|
|
23
|
-
* Called once per observable value when the aggregation is first created.
|
|
24
|
-
* Should install an observe listener that removes entries from the cache
|
|
25
|
-
* when the collection structure changes (e.g. key removal, array shrink).
|
|
26
|
-
*/
|
|
27
|
-
export type CachePruningSetup = (value: any, capturedEntries: PerEntryCache) => void
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @internal
|
|
31
|
-
*
|
|
32
|
-
* Pruning strategy for record / plain-object types.
|
|
33
|
-
* Removes a per-entry cached computed when an object key is removed.
|
|
34
|
-
*/
|
|
35
|
-
export const recordCachePruning: CachePruningSetup = (value, capturedEntries) => {
|
|
36
|
-
observe(value, (change: IObjectDidChange) => {
|
|
37
|
-
if (change.type === "remove") {
|
|
38
|
-
capturedEntries.delete(change.name)
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @internal
|
|
45
|
-
*
|
|
46
|
-
* Pruning strategy for array types.
|
|
47
|
-
* After a splice that shrinks the array, removes per-entry cached computeds
|
|
48
|
-
* for indices that no longer exist (i.e. index >= newLength).
|
|
49
|
-
*/
|
|
50
|
-
export const arrayCachePruning: CachePruningSetup = (value, capturedEntries) => {
|
|
51
|
-
observe(value, (change: IArrayDidChange) => {
|
|
52
|
-
if (change.type === "splice") {
|
|
53
|
-
const newLength = (value as unknown[]).length
|
|
54
|
-
if (capturedEntries.size > newLength) {
|
|
55
|
-
for (const key of capturedEntries.keys()) {
|
|
56
|
-
if ((key as number) >= newLength) {
|
|
57
|
-
capturedEntries.delete(key)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @internal
|
|
67
|
-
*
|
|
68
|
-
* Debug registry mapping observable values to their per-entry cache Maps.
|
|
69
|
-
* Used by tests to verify that stale entries are actually pruned.
|
|
70
|
-
*/
|
|
71
|
-
const __debugPerEntryCaches = new WeakMap<object, PerEntryCache>()
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @internal
|
|
75
|
-
*
|
|
76
|
-
* Returns the number of entries in the per-entry cache for the given observable value,
|
|
77
|
-
* or `undefined` if the value has no cached entries. Used by tests to verify pruning.
|
|
78
|
-
*/
|
|
79
|
-
export function __getPerEntryCacheSize(value: object): number | undefined {
|
|
80
|
-
return __debugPerEntryCaches.get(value)?.size
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @internal
|
|
85
|
-
*
|
|
86
|
-
* Creates a check function that uses per-entry MobX computeds + an aggregation computed
|
|
87
|
-
* for fine-grained reactive type checking.
|
|
88
|
-
*
|
|
89
|
-
* For tweaked (observable) values:
|
|
90
|
-
* 1. Per-entry computeds — each reads only one entry's observable, so changing entry A
|
|
91
|
-
* only invalidates entry A's computed.
|
|
92
|
-
* 2. Aggregation computed — iterates per-entry computeds. Thanks to MobX's change propagation,
|
|
93
|
-
* if a per-entry computed re-evaluates but returns the same result (e.g. null → null),
|
|
94
|
-
* the aggregation body is skipped entirely.
|
|
95
|
-
* 3. Stale entries are pruned reactively via an optional `setupCachePruning` callback
|
|
96
|
-
* (e.g. MobX `observe` listener) that fires on structural mutations, preventing
|
|
97
|
-
* memory leaks for dynamic collections.
|
|
98
|
-
*
|
|
99
|
-
* For non-tweaked values (plain snapshots), falls back to imperative checking.
|
|
100
|
-
*
|
|
101
|
-
* @param iterateEntries Called both inside the aggregation computed (cached path) and
|
|
102
|
-
* for the imperative fallback. Receives a `checkEntry(key)` callback that either
|
|
103
|
-
* returns a cached computed result or performs a direct check, depending on the path.
|
|
104
|
-
* Should call `checkEntry(key)` for each entry and return the first error, or null.
|
|
105
|
-
* @param checkEntry Checks a single entry. For tweaked values, the utility wraps this
|
|
106
|
-
* in a non-keepAlive computed automatically. For non-tweaked values, called directly.
|
|
107
|
-
* @param setupCachePruning Optional callback to install reactive pruning of stale entries.
|
|
108
|
-
* Called once per observable value. Use `recordCachePruning` for records/objects,
|
|
109
|
-
* `arrayCachePruning` for arrays, or omit for fixed-schema types (objects, tuples).
|
|
110
|
-
*/
|
|
111
|
-
export function createPerEntryCachedCheck<K extends PropertyKey>(
|
|
112
|
-
iterateEntries: (
|
|
113
|
-
value: any,
|
|
114
|
-
checkEntry: (entryKey: K) => TypeCheckError | null
|
|
115
|
-
) => TypeCheckError | null,
|
|
116
|
-
checkEntry: (value: any, entryKey: K, path: Path, typeCheckedValue: any) => TypeCheckError | null,
|
|
117
|
-
setupCachePruning?: CachePruningSetup
|
|
118
|
-
): (value: any, path: Path, typeCheckedValue: any) => TypeCheckError | null {
|
|
119
|
-
const perEntryCache = new WeakMap<object, PerEntryCache>()
|
|
120
|
-
const aggregationCache = new WeakMap<object, IComputedValue<TypeCheckError | null>>()
|
|
121
|
-
|
|
122
|
-
// Mutable call context updated before each `.get()` so computed closures
|
|
123
|
-
// always use the latest path/typeCheckedValue. Safe because MobX computed
|
|
124
|
-
// evaluation is synchronous and single-threaded.
|
|
125
|
-
let currentPath: Path
|
|
126
|
-
let currentTypeCheckedValue: any
|
|
127
|
-
|
|
128
|
-
return (value: any, path: Path, typeCheckedValue: any): TypeCheckError | null => {
|
|
129
|
-
if (!isTweakedObject(value, true)) {
|
|
130
|
-
return iterateEntries(value, (key) => checkEntry(value, key, path, typeCheckedValue))
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Update mutable scope before evaluation.
|
|
134
|
-
currentPath = path
|
|
135
|
-
currentTypeCheckedValue = typeCheckedValue
|
|
136
|
-
|
|
137
|
-
let aggr = aggregationCache.get(value)
|
|
138
|
-
if (!aggr) {
|
|
139
|
-
let entries = perEntryCache.get(value)
|
|
140
|
-
if (!entries) {
|
|
141
|
-
entries = new Map()
|
|
142
|
-
perEntryCache.set(value, entries)
|
|
143
|
-
__debugPerEntryCaches.set(value, entries)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const capturedEntries = entries
|
|
147
|
-
|
|
148
|
-
// Install reactive pruning if a strategy was provided.
|
|
149
|
-
setupCachePruning?.(value, capturedEntries)
|
|
150
|
-
|
|
151
|
-
const cachedCheckEntry = (key: K): TypeCheckError | null => {
|
|
152
|
-
let c = capturedEntries.get(key)
|
|
153
|
-
if (!c) {
|
|
154
|
-
c = computed(() => checkEntry(value, key, currentPath, currentTypeCheckedValue))
|
|
155
|
-
capturedEntries.set(key, c)
|
|
156
|
-
}
|
|
157
|
-
return c.get()
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
aggr = computed(() => iterateEntries(value, cachedCheckEntry), { keepAlive: true })
|
|
161
|
-
aggregationCache.set(value, aggr)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return aggr.get()
|
|
165
|
-
}
|
|
166
|
-
}
|
|
File without changes
|