-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
106 lines (90 loc) · 2.33 KB
/
index.js
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
class State {
changed = false
value = ''
}
const state = new State()
export class Machine {
constructor(config, option) {
this.config = config
this.option = option
this.context = Object.assign({}, config.context)
}
transition(current, evt) {
state.changed = false
state.value = current
const ctx = this.context
const { states, on } = this.config
const { actions, guards } = this.option
const node = states[current]
const transition = node?.on?.[evt] || on?.[evt]
if (!transition) {
return state
}
if (typeof transition === 'string') {
state.changed = true
state.value = transition
} else if (Array.isArray(transition)) {
for (var i = 0, len = transition.length; i < len; i++) {
var v = transition[i]
if (typeof v === 'string') {
state.changed = true
state.value = v
} else if (v.cond && guards[v.cond](ctx, evt)) {
state.changed = true
state.value = v.target
break
} else if (v.target && !v.cond) {
state.changed = true
state.value = v.target
break
}
}
} else {
// undefined type
return state
}
if (!state.changed) return state
const newNode = states[state.value]
const { exit } = node
if (typeof exit === 'string') {
actions[exit](ctx)
} else if (Array.isArray(exit)) {
for (var i = 0, len = exit.length; i < len; i++) {
actions[exit[i]](ctx)
}
}
const { entry } = newNode
if (typeof entry === 'string') {
actions[entry](ctx)
} else if (Array.isArray(entry)) {
for (var i = 0, len = entry.length; i < len; i++) {
actions[entry[i]](ctx)
}
}
return state
}
}
class Service {
constructor(machine) {
this.machine = machine
this.state = machine.config.initial
}
start() {}
send(evt) {
const { machine } = this
const s = machine.transition(this.state, evt)
this.state = s.value
return s
}
}
export const interpret = (m) => new Service(m)
export const assign = (obj) => {
const keys = Object.keys(obj)
return (ctx) => {
for (var i = 0, len = keys.length; i < len; i++) {
var key = keys[i]
const val = obj[key]
ctx[key] = typeof val === 'function' ? val(ctx) : val
}
}
}