-
Notifications
You must be signed in to change notification settings - Fork 64
/
Reactor.js
92 lines (82 loc) · 2.53 KB
/
Reactor.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
/**
* @provides javelin-reactor
* @requires javelin-install
* javelin-dynval
* javelin-reactornode
* javelin-util
* @javelin
*/
JX.install('Reactor', {
statics : {
/**
* Return this value from a ReactorNode transformer to indicate that
* its listeners should not be activated.
*/
DoNotPropagate : {},
/**
* For internal use by the Reactor system.
*/
propagatePulse : function(start_pulse, start_node) {
var reverse_post_order =
JX.Reactor._postOrder(start_node).reverse();
start_node.primeValue(start_pulse);
for (var ix = 0; ix < reverse_post_order.length; ix++) {
var node = reverse_post_order[ix];
var pulse = node.getNextPulse();
if (pulse === JX.Reactor.DoNotPropagate) {
continue;
}
var next_pulse = node.getTransformer()(pulse);
var sends_to = node.getListeners();
for (var jx = 0; jx < sends_to.length; jx++) {
sends_to[jx].primeValue(next_pulse);
}
}
},
/**
* For internal use by the Reactor system.
*/
_postOrder : function(node, result, pending) {
if (typeof result === "undefined") {
result = [];
pending = {};
}
pending[node.getGraphID()] = true;
var nexts = node.getListeners();
for (var ix = 0; ix < nexts.length; ix++) {
var next = nexts[ix];
if (pending[next.getGraphID()]) {
continue;
}
JX.Reactor._postOrder(next, result, pending);
}
result.push(node);
return result;
},
// Helper for lift.
_valueNow : function(fn, dynvals) {
var values = [];
for (var ix = 0; ix < dynvals.length; ix++) {
values.push(dynvals[ix].getValueNow());
}
return fn.apply(null, values);
},
/**
* Lift a function over normal values to be a function over dynvals.
* @param fn A function expecting normal values
* @param dynvals Array of DynVals whose instaneous values will be passed
* to fn.
* @return A DynVal representing the changing value of fn applies to dynvals
* over time.
*/
lift : function(fn, dynvals) {
var valueNow = JX.bind(null, JX.Reactor._valueNow, fn, dynvals);
var streams = [];
for (var ix = 0; ix < dynvals.length; ix++) {
streams.push(dynvals[ix].getChanges());
}
var result = new JX.ReactorNode(streams, valueNow);
return new JX.DynVal(result, valueNow());
}
}
});