@tko/observable 4.0.0-alpha7.3 → 4.0.0-beta1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/dist/Subscription.js +31 -0
- package/dist/Subscription.js.map +7 -0
- package/dist/defer.js +24 -0
- package/dist/defer.js.map +7 -0
- package/dist/dependencyDetection.js +47 -0
- package/dist/dependencyDetection.js.map +7 -0
- package/dist/extenders.js +60 -0
- package/dist/extenders.js.map +7 -0
- package/dist/index.cjs +1272 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +7 -0
- package/dist/index.mjs +17 -0
- package/dist/index.mjs.map +7 -0
- package/dist/mappingHelpers.js +58 -0
- package/dist/mappingHelpers.js.map +7 -0
- package/dist/observable.js +120 -910
- package/dist/observable.js.map +7 -1
- package/dist/observableArray.changeTracking.js +126 -0
- package/dist/observableArray.changeTracking.js.map +7 -0
- package/dist/observableArray.js +130 -0
- package/dist/observableArray.js.map +7 -0
- package/dist/subscribable.js +137 -0
- package/dist/subscribable.js.map +7 -0
- package/dist/subscribableSymbol.js +5 -0
- package/dist/subscribableSymbol.js.map +7 -0
- package/package.json +18 -27
- package/dist/observable.es6.js +0 -918
- package/dist/observable.es6.js.map +0 -1
package/dist/observable.js
CHANGED
|
@@ -1,915 +1,125 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import {
|
|
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
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
33
|
-
switch (op[0]) {
|
|
34
|
-
case 0: case 1: t = op; break;
|
|
35
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
36
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
37
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
38
|
-
default:
|
|
39
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
40
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
41
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
42
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
43
|
-
if (t[2]) _.ops.pop();
|
|
44
|
-
_.trys.pop(); continue;
|
|
45
|
-
}
|
|
46
|
-
op = body.call(thisArg, _);
|
|
47
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
48
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function __values(o) {
|
|
53
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
|
54
|
-
if (m) return m.call(o);
|
|
55
|
-
return {
|
|
56
|
-
next: function () {
|
|
57
|
-
if (o && i >= o.length) o = void 0;
|
|
58
|
-
return { value: o && o[i++], done: !o };
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function __read(o, n) {
|
|
64
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
65
|
-
if (!m) return o;
|
|
66
|
-
var i = m.call(o), r, ar = [], e;
|
|
67
|
-
try {
|
|
68
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
69
|
-
}
|
|
70
|
-
catch (error) { e = { error: error }; }
|
|
71
|
-
finally {
|
|
72
|
-
try {
|
|
73
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
74
|
-
}
|
|
75
|
-
finally { if (e) throw e.error; }
|
|
76
|
-
}
|
|
77
|
-
return ar;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function __spread() {
|
|
81
|
-
for (var ar = [], i = 0; i < arguments.length; i++)
|
|
82
|
-
ar = ar.concat(__read(arguments[i]));
|
|
83
|
-
return ar;
|
|
1
|
+
// @tko/observable 🥊 4.0.0-beta1.0 ESM
|
|
2
|
+
import {
|
|
3
|
+
options,
|
|
4
|
+
overwriteLengthPropertyIfSupported
|
|
5
|
+
} from "@tko/utils";
|
|
6
|
+
import * as dependencyDetection from "./dependencyDetection";
|
|
7
|
+
import { deferUpdates } from "./defer";
|
|
8
|
+
import { subscribable, defaultEvent, LATEST_VALUE } from "./subscribable";
|
|
9
|
+
import { valuesArePrimitiveAndEqual } from "./extenders";
|
|
10
|
+
export function observable(initialValue) {
|
|
11
|
+
function Observable() {
|
|
12
|
+
if (arguments.length > 0) {
|
|
13
|
+
if (Observable.isDifferent(Observable[LATEST_VALUE], arguments[0])) {
|
|
14
|
+
Observable.valueWillMutate();
|
|
15
|
+
Observable[LATEST_VALUE] = arguments[0];
|
|
16
|
+
Observable.valueHasMutated();
|
|
17
|
+
}
|
|
18
|
+
return this;
|
|
19
|
+
} else {
|
|
20
|
+
dependencyDetection.registerDependency(Observable);
|
|
21
|
+
return Observable[LATEST_VALUE];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
overwriteLengthPropertyIfSupported(Observable, { value: void 0 });
|
|
25
|
+
Observable[LATEST_VALUE] = initialValue;
|
|
26
|
+
subscribable.fn.init(Observable);
|
|
27
|
+
Object.setPrototypeOf(Observable, observable.fn);
|
|
28
|
+
if (options.deferUpdates) {
|
|
29
|
+
deferUpdates(Observable);
|
|
30
|
+
}
|
|
31
|
+
return Observable;
|
|
84
32
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
33
|
+
observable.fn = {
|
|
34
|
+
equalityComparer: valuesArePrimitiveAndEqual,
|
|
35
|
+
peek() {
|
|
36
|
+
return this[LATEST_VALUE];
|
|
37
|
+
},
|
|
38
|
+
valueHasMutated() {
|
|
39
|
+
this.notifySubscribers(this[LATEST_VALUE], "spectate");
|
|
40
|
+
this.notifySubscribers(this[LATEST_VALUE]);
|
|
41
|
+
},
|
|
42
|
+
valueWillMutate() {
|
|
43
|
+
this.notifySubscribers(this[LATEST_VALUE], "beforeChange");
|
|
44
|
+
},
|
|
45
|
+
modify(fn, peek2 = true) {
|
|
46
|
+
return this(fn(peek2 ? this.peek() : this()));
|
|
47
|
+
},
|
|
48
|
+
isWriteable: true
|
|
49
|
+
};
|
|
50
|
+
function limitNotifySubscribers(value, event) {
|
|
51
|
+
if (!event || event === defaultEvent) {
|
|
52
|
+
this._limitChange(value);
|
|
53
|
+
} else if (event === "beforeChange") {
|
|
54
|
+
this._limitBeforeChange(value);
|
|
55
|
+
} else {
|
|
56
|
+
this._origNotifySubscribers(value, event);
|
|
57
|
+
}
|
|
92
58
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
var
|
|
96
|
-
var
|
|
97
|
-
var
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
59
|
+
subscribable.fn.limit = function limit(limitFunction) {
|
|
60
|
+
var self = this;
|
|
61
|
+
var selfIsObservable = isObservable(self);
|
|
62
|
+
var beforeChange = "beforeChange";
|
|
63
|
+
var ignoreBeforeChange, notifyNextChange, previousValue, pendingValue, didUpdate;
|
|
64
|
+
if (!self._origNotifySubscribers) {
|
|
65
|
+
self._origNotifySubscribers = self.notifySubscribers;
|
|
66
|
+
self.notifySubscribers = limitNotifySubscribers;
|
|
67
|
+
}
|
|
68
|
+
var finish = limitFunction(function() {
|
|
69
|
+
self._notificationIsPending = false;
|
|
70
|
+
if (selfIsObservable && pendingValue === self) {
|
|
71
|
+
pendingValue = self._evalIfChanged ? self._evalIfChanged() : self();
|
|
72
|
+
}
|
|
73
|
+
const shouldNotify = notifyNextChange || didUpdate && self.isDifferent(previousValue, pendingValue);
|
|
74
|
+
self._notifyNextChange = didUpdate = ignoreBeforeChange = false;
|
|
75
|
+
if (shouldNotify) {
|
|
76
|
+
self._origNotifySubscribers(previousValue = pendingValue);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
Object.assign(self, {
|
|
80
|
+
_limitChange(value, isDirty) {
|
|
81
|
+
if (!isDirty || !self._notificationIsPending) {
|
|
82
|
+
didUpdate = !isDirty;
|
|
83
|
+
}
|
|
84
|
+
self._changeSubscriptions = [...self._subscriptions[defaultEvent]];
|
|
85
|
+
self._notificationIsPending = ignoreBeforeChange = true;
|
|
86
|
+
pendingValue = value;
|
|
87
|
+
finish();
|
|
88
|
+
},
|
|
89
|
+
_limitBeforeChange(value) {
|
|
90
|
+
if (!ignoreBeforeChange) {
|
|
91
|
+
previousValue = value;
|
|
92
|
+
self._origNotifySubscribers(value, beforeChange);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
_notifyNextChangeIfValueIsDifferent() {
|
|
96
|
+
if (self.isDifferent(previousValue, self.peek(true))) {
|
|
97
|
+
notifyNextChange = true;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
_recordUpdate() {
|
|
101
|
+
didUpdate = true;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
Object.setPrototypeOf(observable.fn, subscribable.fn);
|
|
106
|
+
var protoProperty = observable.protoProperty = options.protoProperty;
|
|
107
|
+
observable.fn[protoProperty] = observable;
|
|
108
|
+
observable.observablePrototypes = /* @__PURE__ */ new Set([observable]);
|
|
109
|
+
export function isObservable(instance) {
|
|
110
|
+
const proto = typeof instance === "function" && instance[protoProperty];
|
|
111
|
+
if (proto && !observable.observablePrototypes.has(proto)) {
|
|
112
|
+
throw Error("Invalid object that looks like an observable; possibly from another Knockout instance");
|
|
113
|
+
}
|
|
114
|
+
return !!proto;
|
|
145
115
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
begin: begin,
|
|
149
|
-
end: end,
|
|
150
|
-
registerDependency: registerDependency,
|
|
151
|
-
ignore: ignore,
|
|
152
|
-
getDependenciesCount: getDependenciesCount,
|
|
153
|
-
getDependencies: getDependencies,
|
|
154
|
-
isInitial: isInitial,
|
|
155
|
-
ignoreDependencies: ignore
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
//
|
|
159
|
-
function deferUpdates(target) {
|
|
160
|
-
if (target._deferUpdates) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
target._deferUpdates = true;
|
|
164
|
-
target.limit(function (callback) {
|
|
165
|
-
var handle;
|
|
166
|
-
var ignoreUpdates = false;
|
|
167
|
-
return function () {
|
|
168
|
-
if (!ignoreUpdates) {
|
|
169
|
-
tasks.cancel(handle);
|
|
170
|
-
handle = tasks.schedule(callback);
|
|
171
|
-
try {
|
|
172
|
-
ignoreUpdates = true;
|
|
173
|
-
target.notifySubscribers(undefined, 'dirty');
|
|
174
|
-
}
|
|
175
|
-
finally {
|
|
176
|
-
ignoreUpdates = false;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
});
|
|
116
|
+
export function unwrap(value) {
|
|
117
|
+
return isObservable(value) ? value() : value;
|
|
181
118
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
function Subscription(target, observer, disposeCallback) {
|
|
185
|
-
this._target = target;
|
|
186
|
-
this._callback = observer.next;
|
|
187
|
-
this._disposeCallback = disposeCallback;
|
|
188
|
-
this._isDisposed = false;
|
|
189
|
-
this._domNodeDisposalCallback = null;
|
|
190
|
-
}
|
|
191
|
-
Subscription.prototype.dispose = function () {
|
|
192
|
-
if (this._domNodeDisposalCallback) {
|
|
193
|
-
removeDisposeCallback(this._node, this._domNodeDisposalCallback);
|
|
194
|
-
}
|
|
195
|
-
this._isDisposed = true;
|
|
196
|
-
this._disposeCallback();
|
|
197
|
-
};
|
|
198
|
-
Subscription.prototype.disposeWhenNodeIsRemoved = function (node) {
|
|
199
|
-
this._node = node;
|
|
200
|
-
addDisposeCallback(node, this._domNodeDisposalCallback = this.dispose.bind(this));
|
|
201
|
-
};
|
|
202
|
-
// TC39 Observable API
|
|
203
|
-
Subscription.prototype.unsubscribe = function () { this.dispose(); };
|
|
204
|
-
Object.defineProperty(Subscription.prototype, "closed", {
|
|
205
|
-
get: function () { return this._isDisposed; },
|
|
206
|
-
enumerable: true,
|
|
207
|
-
configurable: true
|
|
208
|
-
});
|
|
209
|
-
return Subscription;
|
|
210
|
-
}());
|
|
211
|
-
|
|
212
|
-
//
|
|
213
|
-
var primitiveTypes = {
|
|
214
|
-
'undefined': 1, 'boolean': 1, 'number': 1, 'string': 1
|
|
215
|
-
};
|
|
216
|
-
function valuesArePrimitiveAndEqual(a, b) {
|
|
217
|
-
var oldValueIsPrimitive = (a === null) || (typeof (a) in primitiveTypes);
|
|
218
|
-
return oldValueIsPrimitive ? (a === b) : false;
|
|
219
|
-
}
|
|
220
|
-
function applyExtenders(requestedExtenders) {
|
|
221
|
-
var target = this;
|
|
222
|
-
if (requestedExtenders) {
|
|
223
|
-
objectForEach(requestedExtenders, function (key, value) {
|
|
224
|
-
var extenderHandler = extenders[key];
|
|
225
|
-
if (typeof extenderHandler === 'function') {
|
|
226
|
-
target = extenderHandler(target, value) || target;
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
options.onError(new Error('Extender not found: ' + key));
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
return target;
|
|
234
|
-
}
|
|
235
|
-
/*
|
|
236
|
-
--- DEFAULT EXTENDERS ---
|
|
237
|
-
*/
|
|
238
|
-
// Change when notifications are published.
|
|
239
|
-
function notify(target, notifyWhen) {
|
|
240
|
-
target.equalityComparer = notifyWhen == 'always'
|
|
241
|
-
? null // null equalityComparer means to always notify
|
|
242
|
-
: valuesArePrimitiveAndEqual;
|
|
243
|
-
}
|
|
244
|
-
function deferred(target, option) {
|
|
245
|
-
if (option !== true) {
|
|
246
|
-
throw new Error('The \'deferred\' extender only accepts the value \'true\', because it is not supported to turn deferral off once enabled.');
|
|
247
|
-
}
|
|
248
|
-
deferUpdates(target);
|
|
249
|
-
}
|
|
250
|
-
function rateLimit(target, options$$1) {
|
|
251
|
-
var timeout, method, limitFunction;
|
|
252
|
-
if (typeof options$$1 === 'number') {
|
|
253
|
-
timeout = options$$1;
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
timeout = options$$1.timeout;
|
|
257
|
-
method = options$$1.method;
|
|
258
|
-
}
|
|
259
|
-
// rateLimit supersedes deferred updates
|
|
260
|
-
target._deferUpdates = false;
|
|
261
|
-
limitFunction = method === 'notifyWhenChangesStop' ? debounce : throttle;
|
|
262
|
-
target.limit(function (callback) {
|
|
263
|
-
return limitFunction(callback, timeout);
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
var extenders = {
|
|
267
|
-
notify: notify,
|
|
268
|
-
deferred: deferred,
|
|
269
|
-
rateLimit: rateLimit
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
var _a;
|
|
273
|
-
// Descendants may have a LATEST_VALUE, which if present
|
|
274
|
-
// causes TC39 subscriptions to emit the latest value when
|
|
275
|
-
// subscribed.
|
|
276
|
-
var LATEST_VALUE = Symbol('Knockout latest value');
|
|
277
|
-
function subscribable() {
|
|
278
|
-
Object.setPrototypeOf(this, ko_subscribable_fn);
|
|
279
|
-
ko_subscribable_fn.init(this);
|
|
280
|
-
}
|
|
281
|
-
var defaultEvent = 'change';
|
|
282
|
-
var ko_subscribable_fn = (_a = {},
|
|
283
|
-
_a[SUBSCRIBABLE_SYM] = true,
|
|
284
|
-
_a[Symbol.observable] = function () { return this; },
|
|
285
|
-
_a.init = function (instance) {
|
|
286
|
-
instance._subscriptions = { change: [] };
|
|
287
|
-
instance._versionNumber = 1;
|
|
288
|
-
},
|
|
289
|
-
_a.subscribe = function (callback, callbackTarget, event) {
|
|
290
|
-
var _this = this;
|
|
291
|
-
// TC39 proposed standard Observable { next: () => ... }
|
|
292
|
-
var isTC39Callback = typeof callback === 'object' && callback.next;
|
|
293
|
-
event = event || defaultEvent;
|
|
294
|
-
var observer = isTC39Callback ? callback : {
|
|
295
|
-
next: callbackTarget ? callback.bind(callbackTarget) : callback
|
|
296
|
-
};
|
|
297
|
-
var subscriptionInstance = new Subscription(this, observer, function () {
|
|
298
|
-
arrayRemoveItem(_this._subscriptions[event], subscriptionInstance);
|
|
299
|
-
if (_this.afterSubscriptionRemove) {
|
|
300
|
-
_this.afterSubscriptionRemove(event);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
if (this.beforeSubscriptionAdd) {
|
|
304
|
-
this.beforeSubscriptionAdd(event);
|
|
305
|
-
}
|
|
306
|
-
if (!this._subscriptions[event]) {
|
|
307
|
-
this._subscriptions[event] = [];
|
|
308
|
-
}
|
|
309
|
-
this._subscriptions[event].push(subscriptionInstance);
|
|
310
|
-
// Have TC39 `subscribe` immediately emit.
|
|
311
|
-
// https://github.com/tc39/proposal-observable/issues/190
|
|
312
|
-
if (isTC39Callback && LATEST_VALUE in this) {
|
|
313
|
-
observer.next(this[LATEST_VALUE]);
|
|
314
|
-
}
|
|
315
|
-
return subscriptionInstance;
|
|
316
|
-
},
|
|
317
|
-
_a.notifySubscribers = function (valueToNotify, event) {
|
|
318
|
-
event = event || defaultEvent;
|
|
319
|
-
if (event === defaultEvent) {
|
|
320
|
-
this.updateVersion();
|
|
321
|
-
}
|
|
322
|
-
if (this.hasSubscriptionsForEvent(event)) {
|
|
323
|
-
var subs = event === defaultEvent && this._changeSubscriptions
|
|
324
|
-
|| __spread(this._subscriptions[event]);
|
|
325
|
-
try {
|
|
326
|
-
begin(); // Begin suppressing dependency detection (by setting the top frame to undefined)
|
|
327
|
-
for (var i = 0, subscriptionInstance = void 0; subscriptionInstance = subs[i]; ++i) {
|
|
328
|
-
// In case a subscription was disposed during the arrayForEach cycle, check
|
|
329
|
-
// for isDisposed on each subscription before invoking its callback
|
|
330
|
-
if (!subscriptionInstance._isDisposed) {
|
|
331
|
-
subscriptionInstance._callback(valueToNotify);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
finally {
|
|
336
|
-
end(); // End suppressing dependency detection
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
_a.getVersion = function () {
|
|
341
|
-
return this._versionNumber;
|
|
342
|
-
},
|
|
343
|
-
_a.hasChanged = function (versionToCheck) {
|
|
344
|
-
return this.getVersion() !== versionToCheck;
|
|
345
|
-
},
|
|
346
|
-
_a.updateVersion = function () {
|
|
347
|
-
++this._versionNumber;
|
|
348
|
-
},
|
|
349
|
-
_a.hasSubscriptionsForEvent = function (event) {
|
|
350
|
-
return this._subscriptions[event] && this._subscriptions[event].length;
|
|
351
|
-
},
|
|
352
|
-
_a.getSubscriptionsCount = function (event) {
|
|
353
|
-
if (event) {
|
|
354
|
-
return this._subscriptions[event] && this._subscriptions[event].length || 0;
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
var total = 0;
|
|
358
|
-
objectForEach(this._subscriptions, function (eventName, subscriptions) {
|
|
359
|
-
if (eventName !== 'dirty') {
|
|
360
|
-
total += subscriptions.length;
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
return total;
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
_a.isDifferent = function (oldValue, newValue) {
|
|
367
|
-
return !this.equalityComparer ||
|
|
368
|
-
!this.equalityComparer(oldValue, newValue);
|
|
369
|
-
},
|
|
370
|
-
_a.once = function (cb) {
|
|
371
|
-
var subs = this.subscribe(function (nv) {
|
|
372
|
-
subs.dispose();
|
|
373
|
-
cb(nv);
|
|
374
|
-
});
|
|
375
|
-
},
|
|
376
|
-
_a.when = function (test, returnValue) {
|
|
377
|
-
var _this = this;
|
|
378
|
-
var current = this.peek();
|
|
379
|
-
var givenRv = arguments.length > 1;
|
|
380
|
-
var testFn = typeof test === 'function' ? test : function (v) { return v === test; };
|
|
381
|
-
if (testFn(current)) {
|
|
382
|
-
return options.Promise.resolve(givenRv ? returnValue : current);
|
|
383
|
-
}
|
|
384
|
-
return new options.Promise(function (resolve, reject) {
|
|
385
|
-
var subs = _this.subscribe(function (newValue) {
|
|
386
|
-
if (testFn(newValue)) {
|
|
387
|
-
subs.dispose();
|
|
388
|
-
resolve(givenRv ? returnValue : newValue);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
},
|
|
393
|
-
_a.yet = function (test) {
|
|
394
|
-
var args = [];
|
|
395
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
396
|
-
args[_i - 1] = arguments[_i];
|
|
397
|
-
}
|
|
398
|
-
var testFn = typeof test === 'function' ? test : function (v) { return v === test; };
|
|
399
|
-
var negated = function (v) { return !testFn(v); };
|
|
400
|
-
return this.when.apply(this, __spread([negated], args));
|
|
401
|
-
},
|
|
402
|
-
_a.next = function () {
|
|
403
|
-
var _this = this;
|
|
404
|
-
return new Promise(function (resolve) { return _this.once(resolve); });
|
|
405
|
-
},
|
|
406
|
-
_a.toString = function () { return '[object Object]'; },
|
|
407
|
-
_a.extend = applyExtenders,
|
|
408
|
-
_a);
|
|
409
|
-
// For browsers that support proto assignment, we overwrite the prototype of each
|
|
410
|
-
// observable instance. Since observables are functions, we need Function.prototype
|
|
411
|
-
// to still be in the prototype chain.
|
|
412
|
-
Object.setPrototypeOf(ko_subscribable_fn, Function.prototype);
|
|
413
|
-
subscribable.fn = ko_subscribable_fn;
|
|
414
|
-
|
|
415
|
-
function observable(initialValue) {
|
|
416
|
-
function Observable() {
|
|
417
|
-
if (arguments.length > 0) {
|
|
418
|
-
// Write
|
|
419
|
-
// Ignore writes if the value hasn't changed
|
|
420
|
-
if (Observable.isDifferent(Observable[LATEST_VALUE], arguments[0])) {
|
|
421
|
-
Observable.valueWillMutate();
|
|
422
|
-
Observable[LATEST_VALUE] = arguments[0];
|
|
423
|
-
Observable.valueHasMutated();
|
|
424
|
-
}
|
|
425
|
-
return this; // Permits chained assignments
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
// Read
|
|
429
|
-
registerDependency(Observable); // The caller only needs to be notified of changes if they did a "read" operation
|
|
430
|
-
return Observable[LATEST_VALUE];
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
overwriteLengthPropertyIfSupported(Observable, { value: undefined });
|
|
434
|
-
Observable[LATEST_VALUE] = initialValue;
|
|
435
|
-
subscribable.fn.init(Observable);
|
|
436
|
-
// Inherit from 'observable'
|
|
437
|
-
Object.setPrototypeOf(Observable, observable.fn);
|
|
438
|
-
if (options.deferUpdates) {
|
|
439
|
-
deferUpdates(Observable);
|
|
440
|
-
}
|
|
441
|
-
return Observable;
|
|
442
|
-
}
|
|
443
|
-
// Define prototype for observables
|
|
444
|
-
observable.fn = {
|
|
445
|
-
equalityComparer: valuesArePrimitiveAndEqual,
|
|
446
|
-
peek: function () { return this[LATEST_VALUE]; },
|
|
447
|
-
valueHasMutated: function () {
|
|
448
|
-
this.notifySubscribers(this[LATEST_VALUE], 'spectate');
|
|
449
|
-
this.notifySubscribers(this[LATEST_VALUE]);
|
|
450
|
-
},
|
|
451
|
-
valueWillMutate: function () {
|
|
452
|
-
this.notifySubscribers(this[LATEST_VALUE], 'beforeChange');
|
|
453
|
-
},
|
|
454
|
-
modify: function (fn, peek) {
|
|
455
|
-
if (peek === void 0) { peek = true; }
|
|
456
|
-
return this(fn(peek ? this.peek() : this()));
|
|
457
|
-
},
|
|
458
|
-
// Some observables may not always be writeable, notably computeds.
|
|
459
|
-
isWriteable: true
|
|
460
|
-
};
|
|
461
|
-
// Moved out of "limit" to avoid the extra closure
|
|
462
|
-
function limitNotifySubscribers(value, event) {
|
|
463
|
-
if (!event || event === defaultEvent) {
|
|
464
|
-
this._limitChange(value);
|
|
465
|
-
}
|
|
466
|
-
else if (event === 'beforeChange') {
|
|
467
|
-
this._limitBeforeChange(value);
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
this._origNotifySubscribers(value, event);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
// Add `limit` function to the subscribable prototype
|
|
474
|
-
subscribable.fn.limit = function limit(limitFunction) {
|
|
475
|
-
var self = this;
|
|
476
|
-
var selfIsObservable = isObservable(self);
|
|
477
|
-
var beforeChange = 'beforeChange';
|
|
478
|
-
var ignoreBeforeChange, notifyNextChange, previousValue, pendingValue, didUpdate;
|
|
479
|
-
if (!self._origNotifySubscribers) {
|
|
480
|
-
self._origNotifySubscribers = self.notifySubscribers;
|
|
481
|
-
self.notifySubscribers = limitNotifySubscribers;
|
|
482
|
-
}
|
|
483
|
-
var finish = limitFunction(function () {
|
|
484
|
-
self._notificationIsPending = false;
|
|
485
|
-
// If an observable provided a reference to itself, access it to get the latest value.
|
|
486
|
-
// This allows computed observables to delay calculating their value until needed.
|
|
487
|
-
if (selfIsObservable && pendingValue === self) {
|
|
488
|
-
pendingValue = self._evalIfChanged ? self._evalIfChanged() : self();
|
|
489
|
-
}
|
|
490
|
-
var shouldNotify = notifyNextChange || (didUpdate && self.isDifferent(previousValue, pendingValue));
|
|
491
|
-
self._notifyNextChange = didUpdate = ignoreBeforeChange = false;
|
|
492
|
-
if (shouldNotify) {
|
|
493
|
-
self._origNotifySubscribers(previousValue = pendingValue);
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
Object.assign(self, {
|
|
497
|
-
_limitChange: function (value, isDirty) {
|
|
498
|
-
if (!isDirty || !self._notificationIsPending) {
|
|
499
|
-
didUpdate = !isDirty;
|
|
500
|
-
}
|
|
501
|
-
self._changeSubscriptions = __spread(self._subscriptions[defaultEvent]);
|
|
502
|
-
self._notificationIsPending = ignoreBeforeChange = true;
|
|
503
|
-
pendingValue = value;
|
|
504
|
-
finish();
|
|
505
|
-
},
|
|
506
|
-
_limitBeforeChange: function (value) {
|
|
507
|
-
if (!ignoreBeforeChange) {
|
|
508
|
-
previousValue = value;
|
|
509
|
-
self._origNotifySubscribers(value, beforeChange);
|
|
510
|
-
}
|
|
511
|
-
},
|
|
512
|
-
_notifyNextChangeIfValueIsDifferent: function () {
|
|
513
|
-
if (self.isDifferent(previousValue, self.peek(true /* evaluate */))) {
|
|
514
|
-
notifyNextChange = true;
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
_recordUpdate: function () {
|
|
518
|
-
didUpdate = true;
|
|
519
|
-
}
|
|
520
|
-
});
|
|
521
|
-
};
|
|
522
|
-
Object.setPrototypeOf(observable.fn, subscribable.fn);
|
|
523
|
-
var protoProperty = observable.protoProperty = options.protoProperty;
|
|
524
|
-
observable.fn[protoProperty] = observable;
|
|
525
|
-
// Subclasses can add themselves to observableProperties so that
|
|
526
|
-
// isObservable will be `true`.
|
|
527
|
-
observable.observablePrototypes = new Set([observable]);
|
|
528
|
-
function isObservable(instance) {
|
|
529
|
-
var proto = typeof instance === 'function' && instance[protoProperty];
|
|
530
|
-
if (proto && !observable.observablePrototypes.has(proto)) {
|
|
531
|
-
throw Error('Invalid object that looks like an observable; possibly from another Knockout instance');
|
|
532
|
-
}
|
|
533
|
-
return !!proto;
|
|
534
|
-
}
|
|
535
|
-
function unwrap(value) {
|
|
536
|
-
return isObservable(value) ? value() : value;
|
|
537
|
-
}
|
|
538
|
-
function peek(value) {
|
|
539
|
-
return isObservable(value) ? value.peek() : value;
|
|
540
|
-
}
|
|
541
|
-
function isWriteableObservable(instance) {
|
|
542
|
-
return isObservable(instance) && instance.isWriteable;
|
|
119
|
+
export function peek(value) {
|
|
120
|
+
return isObservable(value) ? value.peek() : value;
|
|
543
121
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
// Use the provided options--each call to trackArrayChanges overwrites the previously set options
|
|
549
|
-
target.compareArrayOptions = {};
|
|
550
|
-
if (options$$1 && typeof options$$1 === 'object') {
|
|
551
|
-
extend(target.compareArrayOptions, options$$1);
|
|
552
|
-
}
|
|
553
|
-
target.compareArrayOptions.sparse = true;
|
|
554
|
-
// Only modify the target observable once
|
|
555
|
-
if (target.cacheDiffForKnownOperation) {
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
var trackingChanges = false;
|
|
559
|
-
var cachedDiff = null;
|
|
560
|
-
var arrayChangeSubscription;
|
|
561
|
-
var pendingNotifications = 0;
|
|
562
|
-
var underlyingNotifySubscribersFunction;
|
|
563
|
-
var underlyingBeforeSubscriptionAddFunction = target.beforeSubscriptionAdd;
|
|
564
|
-
var underlyingAfterSubscriptionRemoveFunction = target.afterSubscriptionRemove;
|
|
565
|
-
// Watch "subscribe" calls, and for array change events, ensure change tracking is enabled
|
|
566
|
-
target.beforeSubscriptionAdd = function (event) {
|
|
567
|
-
if (underlyingBeforeSubscriptionAddFunction) {
|
|
568
|
-
underlyingBeforeSubscriptionAddFunction.call(target, event);
|
|
569
|
-
}
|
|
570
|
-
if (event === arrayChangeEventName) {
|
|
571
|
-
trackChanges();
|
|
572
|
-
}
|
|
573
|
-
};
|
|
574
|
-
// Watch "dispose" calls, and for array change events, ensure change tracking is disabled when all are disposed
|
|
575
|
-
target.afterSubscriptionRemove = function (event) {
|
|
576
|
-
if (underlyingAfterSubscriptionRemoveFunction) {
|
|
577
|
-
underlyingAfterSubscriptionRemoveFunction.call(target, event);
|
|
578
|
-
}
|
|
579
|
-
if (event === arrayChangeEventName && !target.hasSubscriptionsForEvent(arrayChangeEventName)) {
|
|
580
|
-
if (underlyingNotifySubscribersFunction) {
|
|
581
|
-
target.notifySubscribers = underlyingNotifySubscribersFunction;
|
|
582
|
-
underlyingNotifySubscribersFunction = undefined;
|
|
583
|
-
}
|
|
584
|
-
if (arrayChangeSubscription) {
|
|
585
|
-
arrayChangeSubscription.dispose();
|
|
586
|
-
}
|
|
587
|
-
arrayChangeSubscription = null;
|
|
588
|
-
trackingChanges = false;
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
function trackChanges() {
|
|
592
|
-
// Calling 'trackChanges' multiple times is the same as calling it once
|
|
593
|
-
if (trackingChanges) {
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
trackingChanges = true;
|
|
597
|
-
// Intercept "notifySubscribers" to track how many times it was called.
|
|
598
|
-
underlyingNotifySubscribersFunction = target['notifySubscribers'];
|
|
599
|
-
target.notifySubscribers = function (valueToNotify, event) {
|
|
600
|
-
if (!event || event === defaultEvent) {
|
|
601
|
-
++pendingNotifications;
|
|
602
|
-
}
|
|
603
|
-
return underlyingNotifySubscribersFunction.apply(this, arguments);
|
|
604
|
-
};
|
|
605
|
-
// Each time the array changes value, capture a clone so that on the next
|
|
606
|
-
// change it's possible to produce a diff
|
|
607
|
-
var previousContents = [].concat(target.peek() === undefined ? [] : target.peek());
|
|
608
|
-
cachedDiff = null;
|
|
609
|
-
arrayChangeSubscription = target.subscribe(function (currentContents) {
|
|
610
|
-
var changes;
|
|
611
|
-
// Make a copy of the current contents and ensure it's an array
|
|
612
|
-
currentContents = [].concat(currentContents || []);
|
|
613
|
-
// Compute the diff and issue notifications, but only if someone is listening
|
|
614
|
-
if (target.hasSubscriptionsForEvent(arrayChangeEventName)) {
|
|
615
|
-
changes = getChanges(previousContents, currentContents);
|
|
616
|
-
}
|
|
617
|
-
// Eliminate references to the old, removed items, so they can be GCed
|
|
618
|
-
previousContents = currentContents;
|
|
619
|
-
cachedDiff = null;
|
|
620
|
-
pendingNotifications = 0;
|
|
621
|
-
if (changes && changes.length) {
|
|
622
|
-
target.notifySubscribers(changes, arrayChangeEventName);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
function getChanges(previousContents, currentContents) {
|
|
627
|
-
// We try to re-use cached diffs.
|
|
628
|
-
// The scenarios where pendingNotifications > 1 are when using rate-limiting or the Deferred Updates
|
|
629
|
-
// plugin, which without this check would not be compatible with arrayChange notifications. Normally,
|
|
630
|
-
// notifications are issued immediately so we wouldn't be queueing up more than one.
|
|
631
|
-
if (!cachedDiff || pendingNotifications > 1) {
|
|
632
|
-
cachedDiff = trackArrayChanges.compareArrays(previousContents, currentContents, target.compareArrayOptions);
|
|
633
|
-
}
|
|
634
|
-
return cachedDiff;
|
|
635
|
-
}
|
|
636
|
-
target.cacheDiffForKnownOperation = function (rawArray, operationName, args) {
|
|
637
|
-
// Only run if we're currently tracking changes for this observable array
|
|
638
|
-
// and there aren't any pending deferred notifications.
|
|
639
|
-
if (!trackingChanges || pendingNotifications) {
|
|
640
|
-
return;
|
|
641
|
-
}
|
|
642
|
-
var diff = [], arrayLength = rawArray.length, argsLength = args.length, offset = 0;
|
|
643
|
-
function pushDiff(status, value, index) {
|
|
644
|
-
return diff[diff.length] = { 'status': status, 'value': value, 'index': index };
|
|
645
|
-
}
|
|
646
|
-
switch (operationName) {
|
|
647
|
-
case 'push':
|
|
648
|
-
offset = arrayLength;
|
|
649
|
-
case 'unshift':
|
|
650
|
-
for (var index = 0; index < argsLength; index++) {
|
|
651
|
-
pushDiff('added', args[index], offset + index);
|
|
652
|
-
}
|
|
653
|
-
break;
|
|
654
|
-
case 'pop':
|
|
655
|
-
offset = arrayLength - 1;
|
|
656
|
-
case 'shift':
|
|
657
|
-
if (arrayLength) {
|
|
658
|
-
pushDiff('deleted', rawArray[offset], offset);
|
|
659
|
-
}
|
|
660
|
-
break;
|
|
661
|
-
case 'splice':
|
|
662
|
-
// Negative start index means 'from end of array'. After that we clamp to [0...arrayLength].
|
|
663
|
-
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
|
|
664
|
-
var startIndex = Math.min(Math.max(0, args[0] < 0 ? arrayLength + args[0] : args[0]), arrayLength), endDeleteIndex = argsLength === 1 ? arrayLength : Math.min(startIndex + (args[1] || 0), arrayLength), endAddIndex = startIndex + argsLength - 2, endIndex = Math.max(endDeleteIndex, endAddIndex), additions = [], deletions = [];
|
|
665
|
-
for (var index = startIndex, argsIndex = 2; index < endIndex; ++index, ++argsIndex) {
|
|
666
|
-
if (index < endDeleteIndex) {
|
|
667
|
-
deletions.push(pushDiff('deleted', rawArray[index], index));
|
|
668
|
-
}
|
|
669
|
-
if (index < endAddIndex) {
|
|
670
|
-
additions.push(pushDiff('added', args[argsIndex], index));
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
findMovesInArrayComparison(deletions, additions);
|
|
674
|
-
break;
|
|
675
|
-
default:
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
cachedDiff = diff;
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
// Expose compareArrays for testing.
|
|
682
|
-
trackArrayChanges.compareArrays = compareArrays;
|
|
683
|
-
// Add the trackArrayChanges extender so we can use
|
|
684
|
-
// obs.extend({ trackArrayChanges: true })
|
|
685
|
-
extenders.trackArrayChanges = trackArrayChanges;
|
|
686
|
-
|
|
687
|
-
var _a$1;
|
|
688
|
-
function observableArray(initialValues) {
|
|
689
|
-
initialValues = initialValues || [];
|
|
690
|
-
if (typeof initialValues !== 'object' || !('length' in initialValues)) {
|
|
691
|
-
throw new Error('The argument passed when initializing an observable array must be an array, or null, or undefined.');
|
|
692
|
-
}
|
|
693
|
-
var result = observable(initialValues);
|
|
694
|
-
Object.setPrototypeOf(result, observableArray.fn);
|
|
695
|
-
trackArrayChanges(result);
|
|
696
|
-
// ^== result.extend({ trackArrayChanges: true })
|
|
697
|
-
overwriteLengthPropertyIfSupported(result, { get: function () { return result().length; } });
|
|
698
|
-
return result;
|
|
699
|
-
}
|
|
700
|
-
function isObservableArray(instance) {
|
|
701
|
-
return isObservable(instance) && typeof instance.remove === 'function' && typeof instance.push === 'function';
|
|
702
|
-
}
|
|
703
|
-
observableArray.fn = (_a$1 = {
|
|
704
|
-
remove: function (valueOrPredicate) {
|
|
705
|
-
var underlyingArray = this.peek();
|
|
706
|
-
var removedValues = [];
|
|
707
|
-
var predicate = typeof valueOrPredicate === 'function' && !isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
|
|
708
|
-
for (var i = 0; i < underlyingArray.length; i++) {
|
|
709
|
-
var value = underlyingArray[i];
|
|
710
|
-
if (predicate(value)) {
|
|
711
|
-
if (removedValues.length === 0) {
|
|
712
|
-
this.valueWillMutate();
|
|
713
|
-
}
|
|
714
|
-
if (underlyingArray[i] !== value) {
|
|
715
|
-
throw Error("Array modified during remove; cannot remove item");
|
|
716
|
-
}
|
|
717
|
-
removedValues.push(value);
|
|
718
|
-
underlyingArray.splice(i, 1);
|
|
719
|
-
i--;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
if (removedValues.length) {
|
|
723
|
-
this.valueHasMutated();
|
|
724
|
-
}
|
|
725
|
-
return removedValues;
|
|
726
|
-
},
|
|
727
|
-
removeAll: function (arrayOfValues) {
|
|
728
|
-
// If you passed zero args, we remove everything
|
|
729
|
-
if (arrayOfValues === undefined) {
|
|
730
|
-
var underlyingArray = this.peek();
|
|
731
|
-
var allValues = underlyingArray.slice(0);
|
|
732
|
-
this.valueWillMutate();
|
|
733
|
-
underlyingArray.splice(0, underlyingArray.length);
|
|
734
|
-
this.valueHasMutated();
|
|
735
|
-
return allValues;
|
|
736
|
-
}
|
|
737
|
-
// If you passed an arg, we interpret it as an array of entries to remove
|
|
738
|
-
if (!arrayOfValues) {
|
|
739
|
-
return [];
|
|
740
|
-
}
|
|
741
|
-
return this['remove'](function (value) {
|
|
742
|
-
return arrayIndexOf(arrayOfValues, value) >= 0;
|
|
743
|
-
});
|
|
744
|
-
},
|
|
745
|
-
destroy: function (valueOrPredicate) {
|
|
746
|
-
var underlyingArray = this.peek();
|
|
747
|
-
var predicate = typeof valueOrPredicate === 'function' && !isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
|
|
748
|
-
this.valueWillMutate();
|
|
749
|
-
for (var i = underlyingArray.length - 1; i >= 0; i--) {
|
|
750
|
-
var value = underlyingArray[i];
|
|
751
|
-
if (predicate(value)) {
|
|
752
|
-
value['_destroy'] = true;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
this.valueHasMutated();
|
|
756
|
-
},
|
|
757
|
-
destroyAll: function (arrayOfValues) {
|
|
758
|
-
// If you passed zero args, we destroy everything
|
|
759
|
-
if (arrayOfValues === undefined) {
|
|
760
|
-
return this.destroy(function () { return true; });
|
|
761
|
-
}
|
|
762
|
-
// If you passed an arg, we interpret it as an array of entries to destroy
|
|
763
|
-
if (!arrayOfValues) {
|
|
764
|
-
return [];
|
|
765
|
-
}
|
|
766
|
-
return this.destroy(function (value) {
|
|
767
|
-
return arrayIndexOf(arrayOfValues, value) >= 0;
|
|
768
|
-
});
|
|
769
|
-
},
|
|
770
|
-
indexOf: function (item) {
|
|
771
|
-
return arrayIndexOf(this(), item);
|
|
772
|
-
},
|
|
773
|
-
replace: function (oldItem, newItem) {
|
|
774
|
-
var index = this.indexOf(oldItem);
|
|
775
|
-
if (index >= 0) {
|
|
776
|
-
this.valueWillMutate();
|
|
777
|
-
this.peek()[index] = newItem;
|
|
778
|
-
this.valueHasMutated();
|
|
779
|
-
}
|
|
780
|
-
},
|
|
781
|
-
sorted: function (compareFn) {
|
|
782
|
-
return __spread(this()).sort(compareFn);
|
|
783
|
-
},
|
|
784
|
-
reversed: function () {
|
|
785
|
-
return __spread(this()).reverse();
|
|
786
|
-
}
|
|
787
|
-
},
|
|
788
|
-
_a$1[Symbol.iterator] = function () {
|
|
789
|
-
return __generator(this, function (_a) {
|
|
790
|
-
switch (_a.label) {
|
|
791
|
-
case 0: return [5 /*yield**/, __values(this())];
|
|
792
|
-
case 1:
|
|
793
|
-
_a.sent();
|
|
794
|
-
return [2 /*return*/];
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
},
|
|
798
|
-
_a$1);
|
|
799
|
-
Object.setPrototypeOf(observableArray.fn, observable.fn);
|
|
800
|
-
// Populate ko.observableArray.fn with read/write functions from native arrays
|
|
801
|
-
// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
|
|
802
|
-
// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
|
|
803
|
-
arrayForEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function (methodName) {
|
|
804
|
-
observableArray.fn[methodName] = function () {
|
|
805
|
-
// Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
|
|
806
|
-
// (for consistency with mutating regular observables)
|
|
807
|
-
var underlyingArray = this.peek();
|
|
808
|
-
this.valueWillMutate();
|
|
809
|
-
this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);
|
|
810
|
-
var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
|
|
811
|
-
this.valueHasMutated();
|
|
812
|
-
// The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array instead.
|
|
813
|
-
return methodCallResult === underlyingArray ? this : methodCallResult;
|
|
814
|
-
};
|
|
815
|
-
});
|
|
816
|
-
// Populate ko.observableArray.fn with read-only functions from native arrays
|
|
817
|
-
arrayForEach(['slice'], function (methodName) {
|
|
818
|
-
observableArray.fn[methodName] = function () {
|
|
819
|
-
var underlyingArray = this();
|
|
820
|
-
return underlyingArray[methodName].apply(underlyingArray, arguments);
|
|
821
|
-
};
|
|
822
|
-
});
|
|
823
|
-
// Expose for testing.
|
|
824
|
-
observableArray.trackArrayChanges = trackArrayChanges;
|
|
825
|
-
|
|
826
|
-
//
|
|
827
|
-
var maxNestedObservableDepth = 10; // Escape the (unlikely) pathological case where an observable's current value is itself (or similar reference cycle)
|
|
828
|
-
function toJS(rootObject) {
|
|
829
|
-
if (arguments.length == 0) {
|
|
830
|
-
throw new Error('When calling ko.toJS, pass the object you want to convert.');
|
|
831
|
-
}
|
|
832
|
-
// We just unwrap everything at every level in the object graph
|
|
833
|
-
return mapJsObjectGraph(rootObject, function (valueToMap) {
|
|
834
|
-
// Loop because an observable's value might in turn be another observable wrapper
|
|
835
|
-
for (var i = 0; isObservable(valueToMap) && (i < maxNestedObservableDepth); i++) {
|
|
836
|
-
valueToMap = valueToMap();
|
|
837
|
-
}
|
|
838
|
-
return valueToMap;
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
function toJSON(rootObject, replacer, space) {
|
|
842
|
-
var plainJavaScriptObject = toJS(rootObject);
|
|
843
|
-
return JSON.stringify(plainJavaScriptObject, replacer, space);
|
|
844
|
-
}
|
|
845
|
-
function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
|
|
846
|
-
visitedObjects = visitedObjects || new objectLookup();
|
|
847
|
-
rootObject = mapInputCallback(rootObject);
|
|
848
|
-
var canHaveProperties = (typeof rootObject === 'object') && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof RegExp)) && (!(rootObject instanceof Date)) && (!(rootObject instanceof String)) && (!(rootObject instanceof Number)) && (!(rootObject instanceof Boolean));
|
|
849
|
-
if (!canHaveProperties) {
|
|
850
|
-
return rootObject;
|
|
851
|
-
}
|
|
852
|
-
var outputProperties = rootObject instanceof Array ? [] : {};
|
|
853
|
-
visitedObjects.save(rootObject, outputProperties);
|
|
854
|
-
visitPropertiesOrArrayEntries(rootObject, function (indexer) {
|
|
855
|
-
var propertyValue = mapInputCallback(rootObject[indexer]);
|
|
856
|
-
switch (typeof propertyValue) {
|
|
857
|
-
case 'boolean':
|
|
858
|
-
case 'number':
|
|
859
|
-
case 'string':
|
|
860
|
-
case 'function':
|
|
861
|
-
outputProperties[indexer] = propertyValue;
|
|
862
|
-
break;
|
|
863
|
-
case 'object':
|
|
864
|
-
case 'undefined':
|
|
865
|
-
var previouslyMappedValue = visitedObjects.get(propertyValue);
|
|
866
|
-
outputProperties[indexer] = (previouslyMappedValue !== undefined)
|
|
867
|
-
? previouslyMappedValue
|
|
868
|
-
: mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
|
|
869
|
-
break;
|
|
870
|
-
}
|
|
871
|
-
});
|
|
872
|
-
return outputProperties;
|
|
873
|
-
}
|
|
874
|
-
function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
|
|
875
|
-
if (rootObject instanceof Array) {
|
|
876
|
-
for (var i = 0; i < rootObject.length; i++) {
|
|
877
|
-
visitorCallback(i);
|
|
878
|
-
}
|
|
879
|
-
// For arrays, also respect toJSON property for custom mappings (fixes #278)
|
|
880
|
-
if (typeof rootObject['toJSON'] === 'function') {
|
|
881
|
-
visitorCallback('toJSON');
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
else {
|
|
885
|
-
for (var propertyName in rootObject) {
|
|
886
|
-
visitorCallback(propertyName);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
function objectLookup() {
|
|
891
|
-
this.keys = [];
|
|
892
|
-
this.values = [];
|
|
893
|
-
}
|
|
894
|
-
objectLookup.prototype = {
|
|
895
|
-
constructor: objectLookup,
|
|
896
|
-
save: function (key, value) {
|
|
897
|
-
var existingIndex = arrayIndexOf(this.keys, key);
|
|
898
|
-
if (existingIndex >= 0) {
|
|
899
|
-
this.values[existingIndex] = value;
|
|
900
|
-
}
|
|
901
|
-
else {
|
|
902
|
-
this.keys.push(key);
|
|
903
|
-
this.values.push(value);
|
|
904
|
-
}
|
|
905
|
-
},
|
|
906
|
-
get: function (key) {
|
|
907
|
-
var existingIndex = arrayIndexOf(this.keys, key);
|
|
908
|
-
return (existingIndex >= 0) ? this.values[existingIndex] : undefined;
|
|
909
|
-
}
|
|
910
|
-
};
|
|
911
|
-
|
|
912
|
-
//
|
|
913
|
-
|
|
914
|
-
export { dependencyDetection, observable, isObservable, unwrap, peek, isWriteableObservable, isWriteableObservable as isWritableObservable, isSubscribable, subscribable, LATEST_VALUE, observableArray, isObservableArray, trackArrayChanges, arrayChangeEventName, toJS, toJSON, deferUpdates, valuesArePrimitiveAndEqual, applyExtenders, extenders };
|
|
915
|
-
//# sourceMappingURL=observable.js.map
|
|
122
|
+
export function isWriteableObservable(instance) {
|
|
123
|
+
return isObservable(instance) && instance.isWriteable;
|
|
124
|
+
}
|
|
125
|
+
export { isWriteableObservable as isWritableObservable };
|