observable-take.any.js (4186B)
1 test(() => { 2 const results = []; 3 const source = new Observable(subscriber => { 4 subscriber.addTeardown(() => results.push("source teardown")); 5 subscriber.next(1); 6 subscriber.next(2); 7 subscriber.next(3); 8 subscriber.complete(); 9 }); 10 11 const result = source.take(2); 12 13 result.subscribe({ 14 next: v => results.push(v), 15 error: e => results.push(e), 16 complete: () => results.push("complete"), 17 }); 18 19 assert_array_equals(results, [1, 2, "source teardown", "complete"]); 20 }, "take(): Takes the first N values from the source observable, then completes"); 21 22 test(() => { 23 const results = []; 24 const source = new Observable(subscriber => { 25 subscriber.addTeardown(() => results.push("source teardown")); 26 subscriber.next(1); 27 subscriber.next(2); 28 subscriber.next(3); 29 subscriber.complete(); 30 }); 31 32 const result = source.take(5); 33 34 result.subscribe({ 35 next: v => results.push(v), 36 error: e => results.push(e), 37 complete: () => results.push("complete"), 38 }); 39 40 assert_array_equals(results, [1, 2, 3, "source teardown", "complete"], 41 "complete() is immediately forwarded"); 42 }, "take(): Forwards complete()s that happen before the take count is met, " + 43 "and unsubscribes from source Observable"); 44 45 test(() => { 46 const results = []; 47 const error = new Error('source error'); 48 const source = new Observable(subscriber => { 49 subscriber.next(1); 50 subscriber.error(error); 51 }); 52 53 const result = source.take(100); 54 55 result.subscribe({ 56 next: v => results.push(v), 57 error: e => results.push(e), 58 complete: () => results.push("complete"), 59 }); 60 61 assert_array_equals(results, [1, error], "Errors are forwarded"); 62 }, "take(): Should forward errors from the source observable"); 63 64 test(() => { 65 const results = []; 66 const source = new Observable((subscriber) => { 67 results.push("source subscribe"); 68 subscriber.next(1); 69 subscriber.next(2); 70 subscriber.next(3); 71 subscriber.complete(); 72 }); 73 74 const result = source.take(0); 75 76 result.subscribe({ 77 next: v => results.push(v), 78 error: e => results.push(e), 79 complete: () => results.push("complete"), 80 }); 81 82 assert_array_equals(results, ["complete"]); 83 }, "take(): take(0) should not subscribe to the source observable, and " + 84 "should return an observable that immediately completes"); 85 86 test(() => { 87 const results = []; 88 const source = new Observable((subscriber) => { 89 results.push("source subscribe"); 90 subscriber.next(1); 91 subscriber.next(2); 92 subscriber.next(3); 93 subscriber.complete(); 94 }); 95 96 // Per WebIDL, `-1` passed into an `unsigned long long` gets wrapped around 97 // into the maximum value (18446744073709551615), which means the `result` 98 // Observable captures everything that `source` does. 99 const result = source.take(-1); 100 101 result.subscribe({ 102 next: v => results.push(v), 103 error: e => results.push(e), 104 complete: () => results.push("complete"), 105 }); 106 107 assert_array_equals(results, ["source subscribe", 1, 2, 3, "complete"]); 108 }, "take(): Negative count is treated as maximum value"); 109 110 // This tests a regression in Chromium's implementation. In ref-counted 111 // producers, when Subscriber#next() is called, the Subscriber iterates over all 112 // of its "internal observers" [1] and calls "next" on them. However, "next" can 113 // complete the subscription, and modify the "internal observers" list while 114 // Subscriber is iterating over it. This mutation-during-iteration caused a 115 // crash regression in Chromium, which this test covers. 116 // 117 // [1]: https://wicg.github.io/observable/#subscriber-internal-observers 118 promise_test(async () => { 119 async function* asyncNumbers() { 120 yield* [1,2,3,4]; 121 } 122 123 const source = Observable.from(asyncNumbers()); 124 const results = []; 125 126 source.take(1).toArray().then(result => results.push(result)); 127 await source.take(3).toArray().then(result => results.push(result)); 128 129 assert_equals(results.length, 2); 130 assert_array_equals(results[0], [1]); 131 assert_array_equals(results[1], [1, 2, 3]); 132 }, "take(): No crash when take(1) unsubscribes from its source when next() " + 133 "is called, and the Subscriber iterates over the rest of the Observables");