forked from mobxjs/mobx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.ts
More file actions
118 lines (108 loc) · 3.11 KB
/
Copy pathaction.ts
File metadata and controls
118 lines (108 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import {
IDerivation,
endBatch,
fail,
globalState,
invariant,
isSpyEnabled,
spyReportEnd,
spyReportStart,
startBatch,
untrackedEnd,
untrackedStart
} from "../internal"
export interface IAction {
isMobxAction: boolean
}
export function createAction(actionName: string, fn: Function): Function & IAction {
if (process.env.NODE_ENV !== "production") {
invariant(typeof fn === "function", "`action` can only be invoked on functions")
if (typeof actionName !== "string" || !actionName)
fail(`actions should have valid names, got: '${actionName}'`)
}
const res = function() {
return executeAction(actionName, fn, this, arguments)
}
;(res as any).isMobxAction = true
return res as any
}
export function executeAction(actionName: string, fn: Function, scope?: any, args?: IArguments) {
const runInfo = startAction(actionName, fn, scope, args)
try {
return fn.apply(scope, args)
} finally {
endAction(runInfo)
}
}
interface IActionRunInfo {
prevDerivation: IDerivation | null
prevAllowStateChanges: boolean
notifySpy: boolean
startTime: number
}
function startAction(
actionName: string,
fn: Function,
scope: any,
args?: IArguments
): IActionRunInfo {
const notifySpy = isSpyEnabled() && !!actionName
let startTime: number = 0
if (notifySpy && process.env.NODE_ENV !== "production") {
startTime = Date.now()
const l = (args && args.length) || 0
const flattendArgs = new Array(l)
if (l > 0) for (let i = 0; i < l; i++) flattendArgs[i] = args![i]
spyReportStart({
type: "action",
name: actionName,
object: scope,
arguments: flattendArgs
})
}
const prevDerivation = untrackedStart()
startBatch()
const prevAllowStateChanges = allowStateChangesStart(true)
return {
prevDerivation,
prevAllowStateChanges,
notifySpy,
startTime
}
}
function endAction(runInfo: IActionRunInfo) {
allowStateChangesEnd(runInfo.prevAllowStateChanges)
endBatch()
untrackedEnd(runInfo.prevDerivation)
if (runInfo.notifySpy && process.env.NODE_ENV !== "production")
spyReportEnd({ time: Date.now() - runInfo.startTime })
}
export function allowStateChanges<T>(allowStateChanges: boolean, func: () => T): T {
const prev = allowStateChangesStart(allowStateChanges)
let res: T
try {
res = func()
} finally {
allowStateChangesEnd(prev)
}
return res
}
export function allowStateChangesStart(allowStateChanges: boolean) {
const prev = globalState.allowStateChanges
globalState.allowStateChanges = allowStateChanges
return prev
}
export function allowStateChangesEnd(prev: boolean) {
globalState.allowStateChanges = prev
}
export function allowStateChangesInsideComputed<T>(func: () => T): T {
const prev = globalState.computationDepth
globalState.computationDepth = 0
let res: T
try {
res = func()
} finally {
globalState.computationDepth = prev
}
return res
}