rxjs-rails 2.3.0 → 2.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rxjs/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/rx.aggregates.js +115 -27
  4. data/vendor/assets/javascripts/rx.aggregates.min.js +1 -1
  5. data/vendor/assets/javascripts/rx.all.compat.js +2751 -2702
  6. data/vendor/assets/javascripts/rx.all.compat.min.js +3 -3
  7. data/vendor/assets/javascripts/rx.all.js +2605 -2589
  8. data/vendor/assets/javascripts/rx.all.min.js +3 -3
  9. data/vendor/assets/javascripts/rx.async.compat.js +41 -22
  10. data/vendor/assets/javascripts/rx.async.compat.min.js +1 -1
  11. data/vendor/assets/javascripts/rx.async.js +41 -22
  12. data/vendor/assets/javascripts/rx.async.min.js +1 -1
  13. data/vendor/assets/javascripts/rx.backpressure.js +41 -45
  14. data/vendor/assets/javascripts/rx.backpressure.min.js +1 -1
  15. data/vendor/assets/javascripts/rx.binding.js +81 -111
  16. data/vendor/assets/javascripts/rx.binding.min.js +1 -1
  17. data/vendor/assets/javascripts/rx.coincidence.js +567 -486
  18. data/vendor/assets/javascripts/rx.coincidence.min.js +1 -1
  19. data/vendor/assets/javascripts/rx.compat.js +1430 -1532
  20. data/vendor/assets/javascripts/rx.compat.min.js +2 -2
  21. data/vendor/assets/javascripts/rx.core.compat.js +76 -127
  22. data/vendor/assets/javascripts/rx.core.compat.min.js +1 -1
  23. data/vendor/assets/javascripts/rx.core.js +76 -127
  24. data/vendor/assets/javascripts/rx.core.min.js +1 -1
  25. data/vendor/assets/javascripts/rx.experimental.js +36 -36
  26. data/vendor/assets/javascripts/rx.experimental.min.js +1 -1
  27. data/vendor/assets/javascripts/rx.joinpatterns.js +281 -281
  28. data/vendor/assets/javascripts/rx.js +1286 -1421
  29. data/vendor/assets/javascripts/rx.lite.compat.js +1443 -1749
  30. data/vendor/assets/javascripts/rx.lite.compat.min.js +2 -2
  31. data/vendor/assets/javascripts/rx.lite.extras.js +133 -205
  32. data/vendor/assets/javascripts/rx.lite.extras.min.js +1 -1
  33. data/vendor/assets/javascripts/rx.lite.js +1319 -1658
  34. data/vendor/assets/javascripts/rx.lite.min.js +2 -2
  35. data/vendor/assets/javascripts/rx.min.js +2 -2
  36. data/vendor/assets/javascripts/rx.testing.js +302 -322
  37. data/vendor/assets/javascripts/rx.testing.min.js +1 -1
  38. data/vendor/assets/javascripts/rx.time.js +90 -75
  39. data/vendor/assets/javascripts/rx.time.min.js +1 -1
  40. data/vendor/assets/javascripts/rx.virtualtime.js +264 -279
  41. data/vendor/assets/javascripts/rx.virtualtime.min.js +1 -1
  42. metadata +10 -11
@@ -1,4 +1,4 @@
1
- // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
1
+ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
2
 
3
3
  ;(function (factory) {
4
4
  var objectTypes = {
@@ -33,544 +33,486 @@
33
33
  }
34
34
  }.call(this, function (root, exp, Rx, undefined) {
35
35
 
36
- var Observable = Rx.Observable,
37
- CompositeDisposable = Rx.CompositeDisposable,
38
- RefCountDisposable = Rx.RefCountDisposable,
39
- SingleAssignmentDisposable = Rx.SingleAssignmentDisposable,
40
- SerialDisposable = Rx.SerialDisposable,
41
- Subject = Rx.Subject,
42
- observableProto = Observable.prototype,
43
- observableEmpty = Observable.empty,
44
- AnonymousObservable = Rx.AnonymousObservable,
45
- observerCreate = Rx.Observer.create,
46
- addRef = Rx.internals.addRef,
47
- defaultComparer = Rx.internals.isEqual,
48
- noop = Rx.helpers.noop;
36
+ var Observable = Rx.Observable,
37
+ CompositeDisposable = Rx.CompositeDisposable,
38
+ RefCountDisposable = Rx.RefCountDisposable,
39
+ SingleAssignmentDisposable = Rx.SingleAssignmentDisposable,
40
+ SerialDisposable = Rx.SerialDisposable,
41
+ Subject = Rx.Subject,
42
+ observableProto = Observable.prototype,
43
+ observableEmpty = Observable.empty,
44
+ observableNever = Observable.never,
45
+ AnonymousObservable = Rx.AnonymousObservable,
46
+ observerCreate = Rx.Observer.create,
47
+ addRef = Rx.internals.addRef,
48
+ defaultComparer = Rx.internals.isEqual,
49
+ noop = Rx.helpers.noop,
50
+ identity = Rx.helpers.identity;
51
+
52
+
53
+ var Dictionary = (function () {
49
54
 
50
- // Real Dictionary
51
- var primes = [1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647];
52
- var noSuchkey = "no such key";
53
- var duplicatekey = "duplicate key";
55
+ var primes = [1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647],
56
+ noSuchkey = "no such key",
57
+ duplicatekey = "duplicate key";
54
58
 
55
59
  function isPrime(candidate) {
56
- if (candidate & 1 === 0) {
57
- return candidate === 2;
58
- }
59
- var num1 = Math.sqrt(candidate),
60
- num2 = 3;
61
- while (num2 <= num1) {
62
- if (candidate % num2 === 0) {
63
- return false;
64
- }
65
- num2 += 2;
66
- }
67
- return true;
60
+ if (candidate & 1 === 0) { return candidate === 2; }
61
+ var num1 = Math.sqrt(candidate),
62
+ num2 = 3;
63
+ while (num2 <= num1) {
64
+ if (candidate % num2 === 0) { return false; }
65
+ num2 += 2;
66
+ }
67
+ return true;
68
68
  }
69
69
 
70
70
  function getPrime(min) {
71
- var index, num, candidate;
72
- for (index = 0; index < primes.length; ++index) {
73
- num = primes[index];
74
- if (num >= min) {
75
- return num;
76
- }
77
- }
78
- candidate = min | 1;
79
- while (candidate < primes[primes.length - 1]) {
80
- if (isPrime(candidate)) {
81
- return candidate;
82
- }
83
- candidate += 2;
84
- }
85
- return min;
71
+ var index, num, candidate;
72
+ for (index = 0; index < primes.length; ++index) {
73
+ num = primes[index];
74
+ if (num >= min) { return num; }
75
+ }
76
+ candidate = min | 1;
77
+ while (candidate < primes[primes.length - 1]) {
78
+ if (isPrime(candidate)) { return candidate; }
79
+ candidate += 2;
80
+ }
81
+ return min;
86
82
  }
87
83
 
88
84
  function stringHashFn(str) {
89
- var hash = 757602046;
90
- if (!str.length) {
91
- return hash;
92
- }
93
- for (var i = 0, len = str.length; i < len; i++) {
94
- var character = str.charCodeAt(i);
95
- hash = ((hash<<5)-hash)+character;
96
- hash = hash & hash;
97
- }
98
- return hash;
85
+ var hash = 757602046;
86
+ if (!str.length) { return hash; }
87
+ for (var i = 0, len = str.length; i < len; i++) {
88
+ var character = str.charCodeAt(i);
89
+ hash = ((hash<<5)-hash)+character;
90
+ hash = hash & hash;
91
+ }
92
+ return hash;
99
93
  }
100
94
 
101
95
  function numberHashFn(key) {
102
- var c2 = 0x27d4eb2d;
103
- key = (key ^ 61) ^ (key >>> 16);
104
- key = key + (key << 3);
105
- key = key ^ (key >>> 4);
106
- key = key * c2;
107
- key = key ^ (key >>> 15);
108
- return key;
96
+ var c2 = 0x27d4eb2d;
97
+ key = (key ^ 61) ^ (key >>> 16);
98
+ key = key + (key << 3);
99
+ key = key ^ (key >>> 4);
100
+ key = key * c2;
101
+ key = key ^ (key >>> 15);
102
+ return key;
109
103
  }
110
104
 
111
105
  var getHashCode = (function () {
112
- var uniqueIdCounter = 0;
113
-
114
- return function (obj) {
115
- if (obj == null) {
116
- throw new Error(noSuchkey);
117
- }
118
-
119
- // Check for built-ins before tacking on our own for any object
120
- if (typeof obj === 'string') {
121
- return stringHashFn(obj);
122
- }
123
-
124
- if (typeof obj === 'number') {
125
- return numberHashFn(obj);
126
- }
127
-
128
- if (typeof obj === 'boolean') {
129
- return obj === true ? 1 : 0;
130
- }
131
-
132
- if (obj instanceof Date) {
133
- return obj.getTime();
134
- }
135
-
136
- if (obj.getHashCode) {
137
- return obj.getHashCode();
138
- }
106
+ var uniqueIdCounter = 0;
107
+
108
+ return function (obj) {
109
+ if (obj == null) { throw new Error(noSuchkey); }
110
+
111
+ // Check for built-ins before tacking on our own for any object
112
+ if (typeof obj === 'string') { return stringHashFn(obj); }
113
+ if (typeof obj === 'number') { return numberHashFn(obj); }
114
+ if (typeof obj === 'boolean') { return obj === true ? 1 : 0; }
115
+ if (obj instanceof Date) { return numberHashFn(obj.valueOf()); }
116
+ if (obj instanceof RegExp) { return stringHashFn(obj.toString()); }
117
+ if (typeof obj.valueOf === 'function') {
118
+ // Hack check for valueOf
119
+ var valueOf = obj.valueOf();
120
+ if (typeof valueOf === 'number') { return numberHashFn(valueOf); }
121
+ if (typeof obj === 'string') { return stringHashFn(valueOf); }
122
+ }
123
+ if (obj.getHashCode) { return obj.getHashCode(); }
139
124
 
140
- var id = 17 * uniqueIdCounter++;
141
- obj.getHashCode = function () { return id; };
142
- return id;
143
- };
144
- } ());
125
+ var id = 17 * uniqueIdCounter++;
126
+ obj.getHashCode = function () { return id; };
127
+ return id;
128
+ };
129
+ }());
145
130
 
146
131
  function newEntry() {
147
- return { key: null, value: null, next: 0, hashCode: 0 };
132
+ return { key: null, value: null, next: 0, hashCode: 0 };
148
133
  }
149
134
 
150
- // Dictionary implementation
135
+ function Dictionary(capacity, comparer) {
136
+ if (capacity < 0) { throw new Error('out of range'); }
137
+ if (capacity > 0) { this._initialize(capacity); }
138
+
139
+ this.comparer = comparer || defaultComparer;
140
+ this.freeCount = 0;
141
+ this.size = 0;
142
+ this.freeList = -1;
143
+ }
151
144
 
152
- var Dictionary = function (capacity, comparer) {
153
- if (capacity < 0) {
154
- throw new Error('out of range')
155
- }
156
- if (capacity > 0) {
157
- this._initialize(capacity);
158
- }
159
-
160
- this.comparer = comparer || defaultComparer;
161
- this.freeCount = 0;
162
- this.size = 0;
163
- this.freeList = -1;
145
+ var dictionaryProto = Dictionary.prototype;
146
+
147
+ dictionaryProto._initialize = function (capacity) {
148
+ var prime = getPrime(capacity), i;
149
+ this.buckets = new Array(prime);
150
+ this.entries = new Array(prime);
151
+ for (i = 0; i < prime; i++) {
152
+ this.buckets[i] = -1;
153
+ this.entries[i] = newEntry();
154
+ }
155
+ this.freeList = -1;
164
156
  };
165
157
 
166
- Dictionary.prototype._initialize = function (capacity) {
167
- var prime = getPrime(capacity), i;
168
- this.buckets = new Array(prime);
169
- this.entries = new Array(prime);
170
- for (i = 0; i < prime; i++) {
171
- this.buckets[i] = -1;
172
- this.entries[i] = newEntry();
173
- }
174
- this.freeList = -1;
175
- };
176
- Dictionary.prototype.count = function () {
177
- return this.size;
158
+ dictionaryProto.add = function (key, value) {
159
+ return this._insert(key, value, true);
178
160
  };
179
- Dictionary.prototype.add = function (key, value) {
180
- return this._insert(key, value, true);
181
- };
182
- Dictionary.prototype._insert = function (key, value, add) {
183
- if (!this.buckets) {
184
- this._initialize(0);
185
- }
186
- var index3;
187
- var num = getHashCode(key) & 2147483647;
188
- var index1 = num % this.buckets.length;
189
- for (var index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next) {
190
- if (this.entries[index2].hashCode === num && this.comparer(this.entries[index2].key, key)) {
191
- if (add) {
192
- throw new Error(duplicatekey);
193
- }
194
- this.entries[index2].value = value;
195
- return;
196
- }
161
+
162
+ dictionaryProto._insert = function (key, value, add) {
163
+ if (!this.buckets) { this._initialize(0); }
164
+ var index3,
165
+ num = getHashCode(key) & 2147483647,
166
+ index1 = num % this.buckets.length;
167
+ for (var index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next) {
168
+ if (this.entries[index2].hashCode === num && this.comparer(this.entries[index2].key, key)) {
169
+ if (add) { throw new Error(duplicatekey); }
170
+ this.entries[index2].value = value;
171
+ return;
197
172
  }
198
- if (this.freeCount > 0) {
199
- index3 = this.freeList;
200
- this.freeList = this.entries[index3].next;
201
- --this.freeCount;
202
- } else {
203
- if (this.size === this.entries.length) {
204
- this._resize();
205
- index1 = num % this.buckets.length;
206
- }
207
- index3 = this.size;
208
- ++this.size;
173
+ }
174
+ if (this.freeCount > 0) {
175
+ index3 = this.freeList;
176
+ this.freeList = this.entries[index3].next;
177
+ --this.freeCount;
178
+ } else {
179
+ if (this.size === this.entries.length) {
180
+ this._resize();
181
+ index1 = num % this.buckets.length;
209
182
  }
210
- this.entries[index3].hashCode = num;
211
- this.entries[index3].next = this.buckets[index1];
212
- this.entries[index3].key = key;
213
- this.entries[index3].value = value;
214
- this.buckets[index1] = index3;
183
+ index3 = this.size;
184
+ ++this.size;
185
+ }
186
+ this.entries[index3].hashCode = num;
187
+ this.entries[index3].next = this.buckets[index1];
188
+ this.entries[index3].key = key;
189
+ this.entries[index3].value = value;
190
+ this.buckets[index1] = index3;
215
191
  };
216
192
 
217
- Dictionary.prototype._resize = function () {
218
- var prime = getPrime(this.size * 2),
219
- numArray = new Array(prime);
220
- for (index = 0; index < numArray.length; ++index) {
221
- numArray[index] = -1;
222
- }
223
- var entryArray = new Array(prime);
224
- for (index = 0; index < this.size; ++index) {
225
- entryArray[index] = this.entries[index];
226
- }
227
- for (var index = this.size; index < prime; ++index) {
228
- entryArray[index] = newEntry();
229
- }
230
- for (var index1 = 0; index1 < this.size; ++index1) {
231
- var index2 = entryArray[index1].hashCode % prime;
232
- entryArray[index1].next = numArray[index2];
233
- numArray[index2] = index1;
234
- }
235
- this.buckets = numArray;
236
- this.entries = entryArray;
193
+ dictionaryProto._resize = function () {
194
+ var prime = getPrime(this.size * 2),
195
+ numArray = new Array(prime);
196
+ for (index = 0; index < numArray.length; ++index) { numArray[index] = -1; }
197
+ var entryArray = new Array(prime);
198
+ for (index = 0; index < this.size; ++index) { entryArray[index] = this.entries[index]; }
199
+ for (var index = this.size; index < prime; ++index) { entryArray[index] = newEntry(); }
200
+ for (var index1 = 0; index1 < this.size; ++index1) {
201
+ var index2 = entryArray[index1].hashCode % prime;
202
+ entryArray[index1].next = numArray[index2];
203
+ numArray[index2] = index1;
204
+ }
205
+ this.buckets = numArray;
206
+ this.entries = entryArray;
237
207
  };
238
208
 
239
- Dictionary.prototype.remove = function (key) {
240
- if (this.buckets) {
241
- var num = getHashCode(key) & 2147483647;
242
- var index1 = num % this.buckets.length;
243
- var index2 = -1;
244
- for (var index3 = this.buckets[index1]; index3 >= 0; index3 = this.entries[index3].next) {
245
- if (this.entries[index3].hashCode === num && this.comparer(this.entries[index3].key, key)) {
246
- if (index2 < 0) {
247
- this.buckets[index1] = this.entries[index3].next;
248
- } else {
249
- this.entries[index2].next = this.entries[index3].next;
250
- }
251
- this.entries[index3].hashCode = -1;
252
- this.entries[index3].next = this.freeList;
253
- this.entries[index3].key = null;
254
- this.entries[index3].value = null;
255
- this.freeList = index3;
256
- ++this.freeCount;
257
- return true;
258
- } else {
259
- index2 = index3;
260
- }
209
+ dictionaryProto.remove = function (key) {
210
+ if (this.buckets) {
211
+ var num = getHashCode(key) & 2147483647,
212
+ index1 = num % this.buckets.length,
213
+ index2 = -1;
214
+ for (var index3 = this.buckets[index1]; index3 >= 0; index3 = this.entries[index3].next) {
215
+ if (this.entries[index3].hashCode === num && this.comparer(this.entries[index3].key, key)) {
216
+ if (index2 < 0) {
217
+ this.buckets[index1] = this.entries[index3].next;
218
+ } else {
219
+ this.entries[index2].next = this.entries[index3].next;
261
220
  }
221
+ this.entries[index3].hashCode = -1;
222
+ this.entries[index3].next = this.freeList;
223
+ this.entries[index3].key = null;
224
+ this.entries[index3].value = null;
225
+ this.freeList = index3;
226
+ ++this.freeCount;
227
+ return true;
228
+ } else {
229
+ index2 = index3;
230
+ }
262
231
  }
263
- return false;
232
+ }
233
+ return false;
264
234
  };
265
235
 
266
- Dictionary.prototype.clear = function () {
267
- var index, len;
268
- if (this.size <= 0) {
269
- return;
270
- }
271
- for (index = 0, len = this.buckets.length; index < len; ++index) {
272
- this.buckets[index] = -1;
273
- }
274
- for (index = 0; index < this.size; ++index) {
275
- this.entries[index] = newEntry();
276
- }
277
- this.freeList = -1;
278
- this.size = 0;
236
+ dictionaryProto.clear = function () {
237
+ var index, len;
238
+ if (this.size <= 0) { return; }
239
+ for (index = 0, len = this.buckets.length; index < len; ++index) {
240
+ this.buckets[index] = -1;
241
+ }
242
+ for (index = 0; index < this.size; ++index) {
243
+ this.entries[index] = newEntry();
244
+ }
245
+ this.freeList = -1;
246
+ this.size = 0;
279
247
  };
280
248
 
281
- Dictionary.prototype._findEntry = function (key) {
282
- if (this.buckets) {
283
- var num = getHashCode(key) & 2147483647;
284
- for (var index = this.buckets[num % this.buckets.length]; index >= 0; index = this.entries[index].next) {
285
- if (this.entries[index].hashCode === num && this.comparer(this.entries[index].key, key)) {
286
- return index;
287
- }
288
- }
249
+ dictionaryProto._findEntry = function (key) {
250
+ if (this.buckets) {
251
+ var num = getHashCode(key) & 2147483647;
252
+ for (var index = this.buckets[num % this.buckets.length]; index >= 0; index = this.entries[index].next) {
253
+ if (this.entries[index].hashCode === num && this.comparer(this.entries[index].key, key)) {
254
+ return index;
255
+ }
289
256
  }
290
- return -1;
257
+ }
258
+ return -1;
291
259
  };
292
260
 
293
- Dictionary.prototype.count = function () {
294
- return this.size - this.freeCount;
261
+ dictionaryProto.count = function () {
262
+ return this.size - this.freeCount;
295
263
  };
296
264
 
297
- Dictionary.prototype.tryGetValue = function (key) {
298
- var entry = this._findEntry(key);
299
- if (entry >= 0) {
300
- return this.entries[entry].value;
301
- }
302
- return undefined;
265
+ dictionaryProto.tryGetValue = function (key) {
266
+ var entry = this._findEntry(key);
267
+ return entry >= 0 ?
268
+ this.entries[entry].value :
269
+ undefined;
303
270
  };
304
271
 
305
- Dictionary.prototype.getValues = function () {
306
- var index = 0, results = [];
307
- if (this.entries) {
308
- for (var index1 = 0; index1 < this.size; index1++) {
309
- if (this.entries[index1].hashCode >= 0) {
310
- results[index++] = this.entries[index1].value;
311
- }
312
- }
272
+ dictionaryProto.getValues = function () {
273
+ var index = 0, results = [];
274
+ if (this.entries) {
275
+ for (var index1 = 0; index1 < this.size; index1++) {
276
+ if (this.entries[index1].hashCode >= 0) {
277
+ results[index++] = this.entries[index1].value;
278
+ }
313
279
  }
314
- return results;
280
+ }
281
+ return results;
315
282
  };
316
283
 
317
- Dictionary.prototype.get = function (key) {
318
- var entry = this._findEntry(key);
319
- if (entry >= 0) {
320
- return this.entries[entry].value;
321
- }
322
- throw new Error(noSuchkey);
284
+ dictionaryProto.get = function (key) {
285
+ var entry = this._findEntry(key);
286
+ if (entry >= 0) { return this.entries[entry].value; }
287
+ throw new Error(noSuchkey);
323
288
  };
324
289
 
325
- Dictionary.prototype.set = function (key, value) {
326
- this._insert(key, value, false);
290
+ dictionaryProto.set = function (key, value) {
291
+ this._insert(key, value, false);
327
292
  };
328
293
 
329
- Dictionary.prototype.containskey = function (key) {
330
- return this._findEntry(key) >= 0;
294
+ dictionaryProto.containskey = function (key) {
295
+ return this._findEntry(key) >= 0;
331
296
  };
332
297
 
333
- /**
334
- * Correlates the elements of two sequences based on overlapping durations.
335
- *
336
- * @param {Observable} right The right observable sequence to join elements for.
337
- * @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
338
- * @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
339
- * @param {Function} resultSelector A function invoked to compute a result element for any two overlapping elements of the left and right observable sequences. The parameters passed to the function correspond with the elements from the left and right source sequences for which overlap occurs.
340
- * @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
341
- */
342
- observableProto.join = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
343
- var left = this;
344
- return new AnonymousObservable(function (observer) {
345
- var group = new CompositeDisposable(),
346
- leftDone = false,
347
- leftId = 0,
348
- leftMap = new Dictionary(),
349
- rightDone = false,
350
- rightId = 0,
351
- rightMap = new Dictionary();
352
- group.add(left.subscribe(function (value) {
353
- var duration,
354
- expire,
355
- id = leftId++,
356
- md = new SingleAssignmentDisposable(),
357
- result,
358
- values;
359
- leftMap.add(id, value);
360
- group.add(md);
361
- expire = function () {
362
- if (leftMap.remove(id) && leftMap.count() === 0 && leftDone) {
363
- observer.onCompleted();
364
- }
365
- return group.remove(md);
366
- };
367
- try {
368
- duration = leftDurationSelector(value);
369
- } catch (e) {
370
- observer.onError(e);
371
- return;
372
- }
373
- md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), function () { expire(); }));
374
- values = rightMap.getValues();
375
- for (var i = 0; i < values.length; i++) {
376
- try {
377
- result = resultSelector(value, values[i]);
378
- } catch (exception) {
379
- observer.onError(exception);
380
- return;
381
- }
382
- observer.onNext(result);
383
- }
384
- }, observer.onError.bind(observer), function () {
385
- leftDone = true;
386
- if (rightDone || leftMap.count() === 0) {
387
- observer.onCompleted();
388
- }
389
- }));
390
- group.add(right.subscribe(function (value) {
391
- var duration,
392
- expire,
393
- id = rightId++,
394
- md = new SingleAssignmentDisposable(),
395
- result,
396
- values;
397
- rightMap.add(id, value);
398
- group.add(md);
399
- expire = function () {
400
- if (rightMap.remove(id) && rightMap.count() === 0 && rightDone) {
401
- observer.onCompleted();
402
- }
403
- return group.remove(md);
404
- };
405
- try {
406
- duration = rightDurationSelector(value);
407
- } catch (exception) {
408
- observer.onError(exception);
409
- return;
410
- }
411
- md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), function () { expire(); }));
412
- values = leftMap.getValues();
413
- for (var i = 0; i < values.length; i++) {
414
- try {
415
- result = resultSelector(values[i], value);
416
- } catch (exception) {
417
- observer.onError(exception);
418
- return;
419
- }
420
- observer.onNext(result);
421
- }
422
- }, observer.onError.bind(observer), function () {
423
- rightDone = true;
424
- if (leftDone || rightMap.count() === 0) {
425
- observer.onCompleted();
426
- }
427
- }));
428
- return group;
429
- });
430
- };
298
+ return Dictionary;
299
+ }());
431
300
 
432
- /**
433
- * Correlates the elements of two sequences based on overlapping durations, and groups the results.
434
- *
435
- * @param {Observable} right The right observable sequence to join elements for.
436
- * @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
437
- * @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
438
- * @param {Function} resultSelector A function invoked to compute a result element for any element of the left sequence with overlapping elements from the right observable sequence. The first parameter passed to the function is an element of the left sequence. The second parameter passed to the function is an observable sequence with elements from the right sequence that overlap with the left sequence's element.
439
- * @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
440
- */
441
- observableProto.groupJoin = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
442
- var left = this;
443
- return new AnonymousObservable(function (observer) {
444
- var nothing = function () {};
445
- var group = new CompositeDisposable();
446
- var r = new RefCountDisposable(group);
447
- var leftMap = new Dictionary();
448
- var rightMap = new Dictionary();
449
- var leftID = 0;
450
- var rightID = 0;
451
-
452
- group.add(left.subscribe(
453
- function (value) {
454
- var s = new Subject();
455
- var id = leftID++;
456
- leftMap.add(id, s);
457
- var i, len, leftValues, rightValues;
458
-
459
- var result;
460
- try {
461
- result = resultSelector(value, addRef(s, r));
462
- } catch (e) {
463
- leftValues = leftMap.getValues();
464
- for (i = 0, len = leftValues.length; i < len; i++) {
465
- leftValues[i].onError(e);
466
- }
467
- observer.onError(e);
468
- return;
469
- }
470
- observer.onNext(result);
471
-
472
- rightValues = rightMap.getValues();
473
- for (i = 0, len = rightValues.length; i < len; i++) {
474
- s.onNext(rightValues[i]);
475
- }
476
-
477
- var md = new SingleAssignmentDisposable();
478
- group.add(md);
479
-
480
- var expire = function () {
481
- if (leftMap.remove(id)) {
482
- s.onCompleted();
483
- }
484
-
485
- group.remove(md);
486
- };
487
-
488
- var duration;
489
- try {
490
- duration = leftDurationSelector(value);
491
- } catch (e) {
492
- leftValues = leftMap.getValues();
493
- for (i = 0, len = leftMap.length; i < len; i++) {
494
- leftValues[i].onError(e);
495
- }
496
- observer.onError(e);
497
- return;
498
- }
499
-
500
- md.setDisposable(duration.take(1).subscribe(
501
- nothing,
502
- function (e) {
503
- leftValues = leftMap.getValues();
504
- for (i = 0, len = leftValues.length; i < len; i++) {
505
- leftValues[i].onError(e);
506
- }
507
- observer.onError(e);
508
- },
509
- expire)
510
- );
511
- },
512
- function (e) {
513
- var leftValues = leftMap.getValues();
514
- for (var i = 0, len = leftValues.length; i < len; i++) {
515
- leftValues[i].onError(e);
516
- }
517
- observer.onError(e);
518
- },
519
- observer.onCompleted.bind(observer)));
520
-
521
- group.add(right.subscribe(
522
- function (value) {
523
- var leftValues, i, len;
524
- var id = rightID++;
525
- rightMap.add(id, value);
526
-
527
- var md = new SingleAssignmentDisposable();
528
- group.add(md);
529
-
530
- var expire = function () {
531
- rightMap.remove(id);
532
- group.remove(md);
533
- };
534
-
535
- var duration;
536
- try {
537
- duration = rightDurationSelector(value);
538
- } catch (e) {
539
- leftValues = leftMap.getValues();
540
- for (i = 0, len = leftMap.length; i < len; i++) {
541
- leftValues[i].onError(e);
542
- }
543
- observer.onError(e);
544
- return;
545
- }
546
- md.setDisposable(duration.take(1).subscribe(
547
- nothing,
548
- function (e) {
549
- leftValues = leftMap.getValues();
550
- for (i = 0, len = leftMap.length; i < len; i++) {
551
- leftValues[i].onError(e);
552
- }
553
- observer.onError(e);
554
- },
555
- expire)
556
- );
557
-
558
- leftValues = leftMap.getValues();
559
- for (i = 0, len = leftValues.length; i < len; i++) {
560
- leftValues[i].onNext(value);
561
- }
562
- },
563
- function (e) {
564
- var leftValues = leftMap.getValues();
565
- for (var i = 0, len = leftValues.length; i < len; i++) {
566
- leftValues[i].onError(e);
567
- }
568
- observer.onError(e);
569
- }));
301
+ /**
302
+ * Correlates the elements of two sequences based on overlapping durations.
303
+ *
304
+ * @param {Observable} right The right observable sequence to join elements for.
305
+ * @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
306
+ * @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
307
+ * @param {Function} resultSelector A function invoked to compute a result element for any two overlapping elements of the left and right observable sequences. The parameters passed to the function correspond with the elements from the left and right source sequences for which overlap occurs.
308
+ * @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
309
+ */
310
+ observableProto.join = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
311
+ var left = this;
312
+ return new AnonymousObservable(function (observer) {
313
+ var group = new CompositeDisposable();
314
+ var leftDone = false, rightDone = false;
315
+ var leftId = 0, rightId = 0;
316
+ var leftMap = new Dictionary(), rightMap = new Dictionary();
317
+
318
+ group.add(left.subscribe(
319
+ function (value) {
320
+ var id = leftId++;
321
+ var md = new SingleAssignmentDisposable();
322
+
323
+ leftMap.add(id, value);
324
+ group.add(md);
325
+
326
+ var expire = function () {
327
+ leftMap.remove(id) && leftMap.count() === 0 && leftDone && observer.onCompleted();
328
+ group.remove(md);
329
+ };
330
+
331
+ var duration;
332
+ try {
333
+ duration = leftDurationSelector(value);
334
+ } catch (e) {
335
+ observer.onError(e);
336
+ return;
337
+ }
570
338
 
571
- return r;
572
- });
573
- };
339
+ md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), expire));
340
+
341
+ rightMap.getValues().forEach(function (v) {
342
+ var result;
343
+ try {
344
+ result = resultSelector(value, v);
345
+ } catch (exn) {
346
+ observer.onError(exn);
347
+ return;
348
+ }
349
+
350
+ observer.onNext(result);
351
+ });
352
+ },
353
+ observer.onError.bind(observer),
354
+ function () {
355
+ leftDone = true;
356
+ (rightDone || leftMap.count() === 0) && observer.onCompleted();
357
+ })
358
+ );
359
+
360
+ group.add(right.subscribe(
361
+ function (value) {
362
+ var id = rightId++;
363
+ var md = new SingleAssignmentDisposable();
364
+
365
+ rightMap.add(id, value);
366
+ group.add(md);
367
+
368
+ var expire = function () {
369
+ rightMap.remove(id) && rightMap.count() === 0 && rightDone && observer.onCompleted();
370
+ group.remove(md);
371
+ };
372
+
373
+ var duration;
374
+ try {
375
+ duration = rightDurationSelector(value);
376
+ } catch (e) {
377
+ observer.onError(e);
378
+ return;
379
+ }
380
+
381
+ md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), expire));
382
+
383
+ leftMap.getValues().forEach(function (v) {
384
+ var result;
385
+ try {
386
+ result = resultSelector(v, value);
387
+ } catch(exn) {
388
+ observer.onError(exn);
389
+ return;
390
+ }
391
+
392
+ observer.onNext(result);
393
+ });
394
+ },
395
+ observer.onError.bind(observer),
396
+ function () {
397
+ rightDone = true;
398
+ (leftDone || rightMap.count() === 0) && observer.onCompleted();
399
+ })
400
+ );
401
+ return group;
402
+ });
403
+ };
404
+
405
+ /**
406
+ * Correlates the elements of two sequences based on overlapping durations, and groups the results.
407
+ *
408
+ * @param {Observable} right The right observable sequence to join elements for.
409
+ * @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
410
+ * @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
411
+ * @param {Function} resultSelector A function invoked to compute a result element for any element of the left sequence with overlapping elements from the right observable sequence. The first parameter passed to the function is an element of the left sequence. The second parameter passed to the function is an observable sequence with elements from the right sequence that overlap with the left sequence's element.
412
+ * @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
413
+ */
414
+ observableProto.groupJoin = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
415
+ var left = this;
416
+ return new AnonymousObservable(function (observer) {
417
+ var group = new CompositeDisposable();
418
+ var r = new RefCountDisposable(group);
419
+ var leftMap = new Dictionary(), rightMap = new Dictionary();
420
+ var leftId = 0, rightId = 0;
421
+
422
+ function handleError(e) { return function (v) { v.onError(e); }; };
423
+
424
+ group.add(left.subscribe(
425
+ function (value) {
426
+ var s = new Subject();
427
+ var id = leftId++;
428
+ leftMap.add(id, s);
429
+
430
+ var result;
431
+ try {
432
+ result = resultSelector(value, addRef(s, r));
433
+ } catch (e) {
434
+ leftMap.getValues().forEach(handleError(e));
435
+ observer.onError(e);
436
+ return;
437
+ }
438
+ observer.onNext(result);
439
+
440
+ rightMap.getValues().forEach(function (v) { s.onNext(v); });
441
+
442
+ var md = new SingleAssignmentDisposable();
443
+ group.add(md);
444
+
445
+ var expire = function () {
446
+ leftMap.remove(id) && s.onCompleted();
447
+ group.remove(md);
448
+ };
449
+
450
+ var duration;
451
+ try {
452
+ duration = leftDurationSelector(value);
453
+ } catch (e) {
454
+ leftMap.getValues().forEach(handleError(e));
455
+ observer.onError(e);
456
+ return;
457
+ }
458
+
459
+ md.setDisposable(duration.take(1).subscribe(
460
+ noop,
461
+ function (e) {
462
+ leftMap.getValues().forEach(handleError(e));
463
+ observer.onError(e);
464
+ },
465
+ expire)
466
+ );
467
+ },
468
+ function (e) {
469
+ leftMap.getValues().forEach(handleError(e));
470
+ observer.onError(e);
471
+ },
472
+ observer.onCompleted.bind(observer))
473
+ );
474
+
475
+ group.add(right.subscribe(
476
+ function (value) {
477
+ var id = rightId++;
478
+ rightMap.add(id, value);
479
+
480
+ var md = new SingleAssignmentDisposable();
481
+ group.add(md);
482
+
483
+ var expire = function () {
484
+ rightMap.remove(id);
485
+ group.remove(md);
486
+ };
487
+
488
+ var duration;
489
+ try {
490
+ duration = rightDurationSelector(value);
491
+ } catch (e) {
492
+ leftMap.getValues().forEach(handleError(e));
493
+ observer.onError(e);
494
+ return;
495
+ }
496
+ md.setDisposable(duration.take(1).subscribe(
497
+ noop,
498
+ function (e) {
499
+ leftMap.getValues().forEach(handleError(e));
500
+ observer.onError(e);
501
+ },
502
+ expire)
503
+ );
504
+
505
+ leftMap.getValues().forEach(function (v) { v.onNext(value); });
506
+ },
507
+ function (e) {
508
+ leftMap.getValues().forEach(handleError(e));
509
+ observer.onError(e);
510
+ })
511
+ );
512
+
513
+ return r;
514
+ });
515
+ };
574
516
 
575
517
  /**
576
518
  * Projects each element of an observable sequence into zero or more buffers.
@@ -729,5 +671,144 @@
729
671
  ];
730
672
  };
731
673
 
732
- return Rx;
674
+ /**
675
+ * Groups the elements of an observable sequence according to a specified key selector function and comparer and selects the resulting elements by using a specified function.
676
+ *
677
+ * @example
678
+ * var res = observable.groupBy(function (x) { return x.id; });
679
+ * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; });
680
+ * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function (x) { return x.toString(); });
681
+ * @param {Function} keySelector A function to extract the key for each element.
682
+ * @param {Function} [elementSelector] A function to map each source element to an element in an observable group.
683
+ * @param {Function} [comparer] Used to determine whether the objects are equal.
684
+ * @returns {Observable} A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
685
+ */
686
+ observableProto.groupBy = function (keySelector, elementSelector, comparer) {
687
+ return this.groupByUntil(keySelector, elementSelector, observableNever, comparer);
688
+ };
689
+
690
+ /**
691
+ * Groups the elements of an observable sequence according to a specified key selector function.
692
+ * A duration selector function is used to control the lifetime of groups. When a group expires, it receives an OnCompleted notification. When a new element with the same
693
+ * key value as a reclaimed group occurs, the group will be reborn with a new lifetime request.
694
+ *
695
+ * @example
696
+ * var res = observable.groupByUntil(function (x) { return x.id; }, null, function () { return Rx.Observable.never(); });
697
+ * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); });
698
+ * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); }, function (x) { return x.toString(); });
699
+ * @param {Function} keySelector A function to extract the key for each element.
700
+ * @param {Function} durationSelector A function to signal the expiration of a group.
701
+ * @param {Function} [comparer] Used to compare objects. When not specified, the default comparer is used.
702
+ * @returns {Observable}
703
+ * A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
704
+ * If a group's lifetime expires, a new group with the same key value can be created once an element with such a key value is encoutered.
705
+ *
706
+ */
707
+ observableProto.groupByUntil = function (keySelector, elementSelector, durationSelector, comparer) {
708
+ var source = this;
709
+ elementSelector || (elementSelector = identity);
710
+ comparer || (comparer = defaultComparer);
711
+ return new AnonymousObservable(function (observer) {
712
+ function handleError(e) { return function (item) { item.onError(e); }; }
713
+ var map = new Dictionary(0, comparer),
714
+ groupDisposable = new CompositeDisposable(),
715
+ refCountDisposable = new RefCountDisposable(groupDisposable);
716
+
717
+ groupDisposable.add(source.subscribe(function (x) {
718
+ var key;
719
+ try {
720
+ key = keySelector(x);
721
+ } catch (e) {
722
+ map.getValues().forEach(handleError(e));
723
+ observer.onError(e);
724
+ return;
725
+ }
726
+
727
+ var fireNewMapEntry = false,
728
+ writer = map.tryGetValue(key);
729
+ if (!writer) {
730
+ writer = new Subject();
731
+ map.set(key, writer);
732
+ fireNewMapEntry = true;
733
+ }
734
+
735
+ if (fireNewMapEntry) {
736
+ var group = new GroupedObservable(key, writer, refCountDisposable),
737
+ durationGroup = new GroupedObservable(key, writer);
738
+ try {
739
+ duration = durationSelector(durationGroup);
740
+ } catch (e) {
741
+ map.getValues().forEach(handleError(e));
742
+ observer.onError(e);
743
+ return;
744
+ }
745
+
746
+ observer.onNext(group);
747
+
748
+ var md = new SingleAssignmentDisposable();
749
+ groupDisposable.add(md);
750
+
751
+ var expire = function () {
752
+ map.remove(key) && writer.onCompleted();
753
+ groupDisposable.remove(md);
754
+ };
755
+
756
+ md.setDisposable(duration.take(1).subscribe(
757
+ noop,
758
+ function (exn) {
759
+ map.getValues().forEach(handleError(exn));
760
+ observer.onError(exn);
761
+ },
762
+ expire)
763
+ );
764
+ }
765
+
766
+ var element;
767
+ try {
768
+ element = elementSelector(x);
769
+ } catch (e) {
770
+ map.getValues().forEach(handleError(e));
771
+ observer.onError(e);
772
+ return;
773
+ }
774
+
775
+ writer.onNext(element);
776
+ }, function (ex) {
777
+ map.getValues().forEach(handleError(ex));
778
+ observer.onError(ex);
779
+ }, function () {
780
+ map.getValues().forEach(function (item) { item.onCompleted(); });
781
+ observer.onCompleted();
782
+ }));
783
+
784
+ return refCountDisposable;
785
+ });
786
+ };
787
+
788
+ /** @private */
789
+ var GroupedObservable = (function (_super) {
790
+ inherits(GroupedObservable, _super);
791
+
792
+ function subscribe(observer) {
793
+ return this.underlyingObservable.subscribe(observer);
794
+ }
795
+
796
+ /**
797
+ * @constructor
798
+ * @private
799
+ */
800
+ function GroupedObservable(key, underlyingObservable, mergedDisposable) {
801
+ _super.call(this, subscribe);
802
+ this.key = key;
803
+ this.underlyingObservable = !mergedDisposable ?
804
+ underlyingObservable :
805
+ new AnonymousObservable(function (observer) {
806
+ return new CompositeDisposable(mergedDisposable.getDisposable(), underlyingObservable.subscribe(observer));
807
+ });
808
+ }
809
+
810
+ return GroupedObservable;
811
+ }(Observable));
812
+
813
+ return Rx;
733
814
  }));