Skip to content

Commit d9326a0

Browse files
refactor(proxy-state-tree): refactor to single proxifier for tracking state, fix production
1 parent 73f31e1 commit d9326a0

File tree

8 files changed

+245
-217
lines changed

8 files changed

+245
-217
lines changed

packages/node_modules/overmind-react/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const createHook = <A extends Overmind<Configuration>>(
6666
const [debugging] = useState<any>(() => ({
6767
isFirstRender: true,
6868
currentFlushId: 0,
69-
currentComponentsInstaceId: currentComponentInstanceId++,
69+
componentInstanceId: currentComponentInstanceId++,
7070
}))
7171

7272
tree.track((mutations, paths, flushId) => {

packages/node_modules/overmind/src/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,11 @@ export class Overmind<Config extends Configuration> implements Configuration {
228228
}
229229
)
230230
: action(
231-
this.createContext(value, execution, this.proxyStateTree.state)
231+
this.createContext(
232+
value,
233+
execution,
234+
this.proxyStateTree.getMutationTree()
235+
)
232236
)
233237
})
234238
} else {
@@ -240,7 +244,7 @@ export class Overmind<Config extends Configuration> implements Configuration {
240244
this.eventHub.emit(EventType.ACTION_START, execution)
241245
this.eventHub.emit(EventType.OPERATOR_START, execution)
242246

243-
const mutationTree = this.proxyStateTree.getMutationTree().track()
247+
const mutationTree = this.proxyStateTree.getMutationTree()
244248

245249
mutationTree.onMutation((mutation) => {
246250
this.eventHub.emit(EventType.MUTATIONS, {
@@ -741,7 +745,7 @@ export function mutate<Input, Config extends Configuration = TheConfig>(
741745
if (err) next(err)
742746
else {
743747
startDebugOperator('mutate', operation, context)
744-
const mutationsTree = context.proxyStateTree.getMutationTree().track()
748+
const mutationsTree = context.proxyStateTree.getMutationTree()
745749
operation({ ...context, state: mutationsTree.state })
746750
const newContext = createContext(context, context.value)
747751
context.execution.emit(EventType.MUTATIONS, {

packages/node_modules/proxy-state-tree/src/Proxyfier.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { TTree } from './'
2-
import { ITrackStateTree } from './TrackStateTree'
3-
import { ITrackMutationTree } from './TrackMutationTree'
1+
import { TTree, ITrackStateTree, ITrackMutationTree, IMutation } from './types'
42

53
const isPlainObject = require('is-plain-object')
64

@@ -19,28 +17,50 @@ const arrayMutations = new Set([
1917
'copyWithin',
2018
])
2119

20+
const removeProxyMutations = ['set', 'splice', 'shift', 'unshift']
21+
2222
export class Proxifier {
23-
constructor(private tree: TTree) {}
23+
private proxyCache = {}
24+
constructor(private tree: TTree) {
25+
tree.master.onMutation(this.removeProxies)
26+
}
2427
private concat(path, prop) {
2528
return path ? path + '.' + prop : prop
2629
}
2730

28-
private shouldTrackMutations(path) {
31+
addProxyToCache(path: string, proxy: any) {
32+
return (this.proxyCache[path] = proxy)
33+
}
34+
getProxyFromCache(path: string) {
35+
return this.proxyCache[path]
36+
}
37+
38+
shouldTrackMutations(path) {
2939
return (
3040
this.tree.master.options.devmode ||
3141
(path && this.tree.master.pathDependencies[path])
3242
)
3343
}
3444

35-
private ensureMutationTrackingIsEnabled(path) {
45+
removeProxies = (mutation: IMutation) => {
46+
if (removeProxyMutations.includes(mutation.method)) {
47+
for (let path in this.proxyCache) {
48+
if (path.indexOf(mutation.path) === 0) {
49+
delete this.proxyCache[path]
50+
}
51+
}
52+
}
53+
}
54+
55+
ensureMutationTrackingIsEnabled(path) {
3656
if (this.tree.master.options.devmode && !this.tree.canMutate()) {
3757
throw new Error(
3858
`proxy-state-tree - You are mutating the path "${path}", but it is not allowed`
3959
)
4060
}
4161
}
4262

43-
private ensureValueDosntExistInStateTreeElsewhere(value) {
63+
ensureValueDosntExistInStateTreeElsewhere(value) {
4464
if (value && value[IS_PROXY] === true) {
4565
throw new Error(
4666
`proxy-state-tree - You are trying to insert a value that already exists in the state tree on path "${
@@ -50,17 +70,24 @@ export class Proxifier {
5070
}
5171
}
5272

53-
private trackPath(path: string) {
73+
trackPath(path: string) {
5474
if (this.tree.canTrack()) {
55-
const trackStateAccessTree = this.tree as ITrackStateTree<any>
56-
trackStateAccessTree.addTrackingPath(path)
75+
const trackStateTree = this.tree.master.currentTree as ITrackStateTree<
76+
any
77+
>
78+
79+
if (!trackStateTree) {
80+
return
81+
}
82+
83+
trackStateTree.addTrackingPath(path)
5784
}
5885
}
5986
// With tracking trees we want to ensure that we are always
6087
// on the currently tracked tree. This ensures when we access
6188
// a tracking proxy that is not part of the current tracking tree (pass as prop)
6289
// we move the ownership to the current tracker
63-
private getTrackingTree() {
90+
getTrackingTree() {
6491
const currentTree = this.tree.master.currentTree
6592

6693
if (currentTree) {
@@ -81,10 +108,9 @@ export class Proxifier {
81108
var proxifier = this
82109

83110
return (
84-
proxifier.tree.master.getProxy(path, proxifier.tree) ||
85-
proxifier.tree.master.addProxy(
111+
this.getProxyFromCache(path) ||
112+
this.addProxyToCache(
86113
path,
87-
proxifier.tree,
88114
new Proxy(value, {
89115
get(target, prop) {
90116
if (prop === IS_PROXY) return true
@@ -102,6 +128,7 @@ export class Proxifier {
102128

103129
const trackingTree = proxifier.getTrackingTree()
104130
const nestedPath = proxifier.concat(path, prop)
131+
105132
trackingTree && trackingTree.proxifier.trackPath(nestedPath)
106133

107134
if (
@@ -152,10 +179,9 @@ export class Proxifier {
152179
const proxifier = this
153180

154181
return (
155-
proxifier.tree.master.getProxy(path, proxifier.tree) ||
156-
proxifier.tree.master.addProxy(
182+
this.getProxyFromCache(path) ||
183+
this.addProxyToCache(
157184
path,
158-
proxifier.tree,
159185
new Proxy(value, {
160186
get(target, prop) {
161187
if (prop === IS_PROXY) return true
@@ -168,6 +194,7 @@ export class Proxifier {
168194
const trackingTree = proxifier.getTrackingTree()
169195
const targetValue = target[prop]
170196
const nestedPath = proxifier.concat(path, prop)
197+
171198
trackingTree && trackingTree.proxifier.trackPath(nestedPath)
172199

173200
if (typeof targetValue === 'function') {

packages/node_modules/proxy-state-tree/src/TrackMutationTree.ts

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,24 @@
1-
import { IProxyStateTree, VALUE } from './'
1+
import {
2+
IProxyStateTree,
3+
ITrackMutationTree,
4+
IMutationCallback,
5+
IMutation,
6+
IProxifier,
7+
} from './types'
28
import { Proxifier } from './Proxyfier'
39

4-
export interface IMutation {
5-
method: string
6-
path: string
7-
args: any[]
8-
}
9-
10-
export interface IMutationCallback {
11-
(mutation: IMutation, paths: Set<string>, flushId: number): void
12-
}
13-
14-
export interface ITrackMutationTree<T extends object> {
15-
addMutation(mutation: IMutation, objectChangePath?: string): void
16-
onMutation(callback: IMutationCallback): void
17-
canTrack(): boolean
18-
canMutate(): boolean
19-
dispose(): ITrackMutationTree<T>
20-
track(): ITrackMutationTree<T>
21-
master: IProxyStateTree<T>
22-
proxifier: Proxifier
23-
state: T
24-
}
25-
2610
export class TrackMutationTree<T extends object>
2711
implements ITrackMutationTree<T> {
2812
private mutationCallbacks: IMutationCallback[] = []
2913
master: IProxyStateTree<T>
3014
state: T
31-
proxifier: Proxifier
15+
proxifier: IProxifier<T>
3216
isTracking: boolean = false
3317
constructor(master: IProxyStateTree<T>) {
18+
this.isTracking = true
3419
this.master = master
3520
this.proxifier = new Proxifier(this)
36-
this.state = this.proxifier.proxify(master.state[VALUE], '')
21+
this.state = this.proxifier.proxify(master.sourceState, '')
3722
}
3823
addMutation(mutation: IMutation, objectChangePath: string) {
3924
this.master.addMutation(mutation, objectChangePath)
@@ -48,10 +33,6 @@ export class TrackMutationTree<T extends object>
4833
)
4934
}
5035
}
51-
track() {
52-
this.isTracking = true
53-
return this
54-
}
5536
onMutation(callback: IMutationCallback) {
5637
this.mutationCallbacks.push(callback)
5738
}

packages/node_modules/proxy-state-tree/src/TrackStateTree.ts

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,37 @@
1-
import { IProxyStateTree, VALUE, IMutation } from './'
2-
import { Proxifier } from './Proxyfier'
3-
4-
export interface ITrackCallback {
5-
(
6-
mutations: IMutation[],
7-
paths: Set<string>,
8-
flushId: number,
9-
isAsync: boolean
10-
): void
11-
}
12-
13-
export interface ITrackScopedCallback<T extends object> {
14-
(tree: TrackStateTree<T>): any
15-
}
16-
17-
export interface ITrackStateTree<T extends object> {
18-
addTrackingPath(path: string): void
19-
track(cb?: ITrackCallback)
20-
trackScope(scope: ITrackScopedCallback<T>, callback?: ITrackCallback): any
21-
canTrack(): boolean
22-
canMutate(): boolean
23-
dispose(): ITrackStateTree<T>
24-
master: IProxyStateTree<T>
25-
proxifier: Proxifier
26-
state: T
27-
pathDependencies: Set<string>
28-
}
1+
import {
2+
IProxyStateTree,
3+
ITrackStateTree,
4+
ITrackCallback,
5+
IProxifier,
6+
ITrackScopedCallback,
7+
} from './types'
298

309
export class TrackStateTree<T extends object> implements ITrackStateTree<T> {
3110
master: IProxyStateTree<T>
3211
pathDependencies: Set<string> = new Set()
33-
isTracking: boolean = false
34-
callback: ITrackCallback | null
12+
callback: ITrackCallback
3513
state: T
36-
proxifier: Proxifier
14+
proxifier: IProxifier<T>
3715
constructor(master: IProxyStateTree<T>) {
3816
this.master = master
39-
this.proxifier = new Proxifier(this)
40-
this.state = this.proxifier.proxify(master.state[VALUE], '')
17+
this.proxifier = master.proxifier
18+
this.state = master.state
4119
}
4220
canMutate() {
4321
return false
4422
}
4523
canTrack() {
46-
return this.isTracking
24+
return true
4725
}
4826
addTrackingPath(path: string) {
4927
this.pathDependencies.add(path)
5028

51-
if (!this.callback) {
52-
return
29+
if (this.callback) {
30+
this.master.addPathDependency(path, this.callback)
5331
}
54-
55-
this.master.addPathDependency(path, this.callback)
5632
}
5733
track(cb?: ITrackCallback) {
58-
this.isTracking = true
59-
this.master.currentTree = this
34+
this.master.changeTrackStateTree(this)
6035

6136
if (this.callback) {
6237
for (let path of this.pathDependencies) {
@@ -78,12 +53,13 @@ export class TrackStateTree<T extends object> implements ITrackStateTree<T> {
7853
return this
7954
}
8055
trackScope(scope: ITrackScopedCallback<T>, cb?: ITrackCallback) {
81-
const previousTree = this.master.currentTree
56+
const previousPreviousTree = this.master.previousTree
57+
const previousCurrentTree = this.master.currentTree
8258
this.master.currentTree = this
8359
this.track(cb)
8460
const result = scope(this)
85-
this.isTracking = false
86-
this.master.currentTree = previousTree
61+
this.master.currentTree = previousCurrentTree
62+
this.master.previousTree = previousPreviousTree
8763

8864
return result
8965
}

0 commit comments

Comments
 (0)