-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstate.js
More file actions
85 lines (72 loc) · 1.61 KB
/
state.js
File metadata and controls
85 lines (72 loc) · 1.61 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
/**
* Internal use
*/
const parentMap = new WeakMap();
/**
* The root of all states
*/
class EmptyState {
defined(key) {
return false;
}
delete(key) {
return key === this.key ? this : new EmptyKeyState(this, key);
}
get(key) {
if (key === 'global') {
return global;
}
throw new Error(`"${key}" is not defined`);
}
set(key, value) {
if (key === this.key && value === this.value) {
return this;
}
return new KeyValueState(this, key, value);
}
store(key, value) {
const circularStateReference = value.set(key);
circularStateReference.value = circularStateReference;
return this.set(key, circularStateReference);
}
}
/**
* A state representing a deleted key
*/
class EmptyKeyState extends EmptyState {
constructor(parent, key) {
super();
parentMap.set(this, parent);
this.key = key;
}
defined(key) {
return key === this.key ? false : parentMap.get(this).defined(key);
}
get(key) {
if (key === this.key) {
throw new Error(`"${key}" is not defined`);
}
return parentMap.get(this).get(key);
}
}
/**
* A state representing a key value pair
*/
class KeyValueState extends EmptyState {
constructor(parent, key, value) {
super();
parentMap.set(this, parent);
this.key = key;
this.value = value;
}
defined(key) {
return key === this.key ? true : parentMap.get(this).defined(key);
}
delete(key) {
return this.defined(key) ? new EmptyKeyState(this, key) : this;
}
get(key) {
return key === this.key ? this.value : parentMap.get(this).get(key);
}
}
module.exports = EmptyState;