-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreactive-var.js
142 lines (130 loc) · 13.5 KB
/
reactive-var.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//////////////////////////////////////////////////////////////////////////
// //
// This is a generated file. You can view the original //
// source in your browser if your browser supports source maps. //
// //
// If you are using Chrome, open the Developer Tools and click the gear //
// icon in its lower right corner. In the General Settings panel, turn //
// on 'Enable source maps'. //
// //
// If you are using Firefox 23, go to `about:config` and set the //
// `devtools.debugger.source-maps-enabled` preference to true. //
// (The preference should be on by default in Firefox 24; versions //
// older than 23 do not support source maps.) //
// //
//////////////////////////////////////////////////////////////////////////
define(function (require) {
var Package = {};
var Meteor = require('./meteor');
var Tracker = require('./tracker');
var Deps = Tracker._Deps;
/* Package-scope variables */
var ReactiveVar;
(function () {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/reactive-var/reactive-var.js //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/* // 1
* ## [new] ReactiveVar(initialValue, [equalsFunc]) // 2
* // 3
* A ReactiveVar holds a single value that can be get and set, // 4
* such that calling `set` will invalidate any Computations that // 5
* called `get`, according to the usual contract for reactive // 6
* data sources. // 7
* // 8
* A ReactiveVar is much like a Session variable -- compare `foo.get()` // 9
* to `Session.get("foo")` -- but it doesn't have a global name and isn't // 10
* automatically migrated across hot code pushes. Also, while Session // 11
* variables can only hold JSON or EJSON, ReactiveVars can hold any value. // 12
* // 13
* An important property of ReactiveVars, which is sometimes the reason // 14
* to use one, is that setting the value to the same value as before has // 15
* no effect, meaning ReactiveVars can be used to absorb extra // 16
* invalidations that wouldn't serve a purpose. However, by default, // 17
* ReactiveVars are extremely conservative about what changes they // 18
* absorb. Calling `set` with an object argument will *always* trigger // 19
* invalidations, because even if the new value is `===` the old value, // 20
* the object may have been mutated. You can change the default behavior // 21
* by passing a function of two arguments, `oldValue` and `newValue`, // 22
* to the constructor as `equalsFunc`. // 23
* // 24
* This class is extremely basic right now, but the idea is to evolve // 25
* it into the ReactiveVar of Geoff's Lickable Forms proposal. // 26
*/ // 27
// 28
/** // 29
* @class // 30
* @instanceName reactiveVar // 31
* @summary Constructor for a ReactiveVar, which represents a single reactive variable. // 32
* @locus Client // 33
* @param {Any} initialValue The initial value to set. `equalsFunc` is ignored when setting the initial value. // 34
* @param {Function} [equalsFunc] Optional. A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null.
*/ // 36
ReactiveVar = function (initialValue, equalsFunc) { // 37
if (! (this instanceof ReactiveVar)) // 38
// called without `new` // 39
return new ReactiveVar(initialValue, equalsFunc); // 40
// 41
this.curValue = initialValue; // 42
this.equalsFunc = equalsFunc; // 43
this.dep = new Tracker.Dependency; // 44
}; // 45
// 46
ReactiveVar._isEqual = function (oldValue, newValue) { // 47
var a = oldValue, b = newValue; // 48
// Two values are "equal" here if they are `===` and are // 49
// number, boolean, string, undefined, or null. // 50
if (a !== b) // 51
return false; // 52
else // 53
return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') || // 54
(typeof a === 'string')); // 55
}; // 56
// 57
/** // 58
* @summary Returns the current value of the ReactiveVar, establishing a reactive dependency. // 59
* @locus Client // 60
*/ // 61
ReactiveVar.prototype.get = function () { // 62
if (Tracker.active) // 63
this.dep.depend(); // 64
// 65
return this.curValue; // 66
}; // 67
// 68
/** // 69
* @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value.
* @locus Client // 71
* @param {Any} newValue // 72
*/ // 73
ReactiveVar.prototype.set = function (newValue) { // 74
var oldValue = this.curValue; // 75
// 76
if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue)) // 77
// value is same as last time // 78
return; // 79
// 80
this.curValue = newValue; // 81
this.dep.changed(); // 82
}; // 83
// 84
ReactiveVar.prototype.toString = function () { // 85
return 'ReactiveVar{' + this.get() + '}'; // 86
}; // 87
// 88
ReactiveVar.prototype._numListeners = function() { // 89
// Tests want to know. // 90
// Accesses a private field of Tracker.Dependency. // 91
var count = 0; // 92
for (var id in this.dep._dependentsById) // 93
count++; // 94
return count; // 95
}; // 96
// 97
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
return ReactiveVar;
});