From 6891efb90dd33062831023a0b5aa62019b3c4175 Mon Sep 17 00:00:00 2001 From: demensky Date: Tue, 24 Jan 2023 19:41:42 +0200 Subject: [PATCH 01/15] feat(operator): removed deprecated `merge` operator BREAKING CHANGE: The `merge` operator is no longer available. Use `mergeWith`. --- spec-dtslint/operators/merge-spec.ts | 88 ---------------------------- spec/Observable-spec.ts | 6 +- spec/operators/merge-legacy-spec.ts | 23 -------- src/internal/operators/merge.ts | 33 ----------- src/internal/operators/mergeWith.ts | 8 ++- src/operators/index.ts | 1 - 6 files changed, 9 insertions(+), 150 deletions(-) delete mode 100644 spec-dtslint/operators/merge-spec.ts delete mode 100644 spec/operators/merge-legacy-spec.ts delete mode 100644 src/internal/operators/merge.ts diff --git a/spec-dtslint/operators/merge-spec.ts b/spec-dtslint/operators/merge-spec.ts deleted file mode 100644 index 71bd76ac2a..0000000000 --- a/spec-dtslint/operators/merge-spec.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { asyncScheduler } from 'rxjs'; -import { merge } from 'rxjs/operators'; -import { a$, b$, c$, d$, e$, f$} from '../helpers'; - -it('should accept no parameter', () => { - const res = a$.pipe(merge()); // $ExpectType Observable -}); - -it('should infer correctly with scheduler param', () => { - const res = a$.pipe(merge(asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with concurrent param', () => { - const res = a$.pipe(merge(3)); // $ExpectType Observable -}); - -it('should infer correctly with concurrent and scheduler param', () => { - const res = a$.pipe(merge(3, asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with 1 Observable param', () => { - const res = a$.pipe(merge(b$)); // $ExpectType Observable -}); - -it('should infer correctly with 2 Observable param', () => { - const res = a$.pipe(merge(b$, c$)); // $ExpectType Observable -}); - -it('should infer correctly with 3 Observable param', () => { - const res = a$.pipe(merge(b$, c$, d$)); // $ExpectType Observable -}); - -it('should infer correctly with 4 Observable param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$)); // $ExpectType Observable -}); - -it('should infer correctly with 5 Observable param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$, f$)); // $ExpectType Observable -}); - -it('should infer correctly with 1 Observable and concurrent param', () => { - const res = a$.pipe(merge(b$, 1)); // $ExpectType Observable -}); - -it('should infer correctly with 2 Observable and concurrent param', () => { - const res = a$.pipe(merge(b$, c$, 1)); // $ExpectType Observable -}); - -it('should infer correctly with 3 Observable and concurrent param', () => { - const res = a$.pipe(merge(b$, c$, d$, 1)); // $ExpectType Observable -}); - -it('should infer correctly with 4 Observable and concurrent param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$, 1)); // $ExpectType Observable -}); - -it('should infer correctly with 5 Observable and concurrent param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$, f$, 1)); // $ExpectType Observable -}); - -it('should infer correctly with 1 Observable, concurrent, and scheduler param', () => { - const res = a$.pipe(merge(b$, 1, asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with 2 Observable, concurrent, and scheduler param', () => { - const res = a$.pipe(merge(b$, c$, 1, asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with 3 Observable, concurrent, and scheduler param', () => { - const res = a$.pipe(merge(b$, c$, d$, 1, asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with 4 Observable, concurrent, and scheduler param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$, 1, asyncScheduler)); // $ExpectType Observable -}); - -it('should infer correctly with 5 Observable, concurrent, and scheduler param', () => { - const res = a$.pipe(merge(b$, c$, d$, e$, f$, 1, asyncScheduler)); // $ExpectType Observable -}); - -// TODO: Fix this when the both merge operator and merge creator function has been fix -// see: https://github.com/ReactiveX/rxjs/pull/4371#issuecomment-441124096 -// Comment is about combineLater, but, it's the same problem to fix -// it('should infer correctly with array param', () => { -// const res = of(1, 2, 3); -// const b = [of('a', 'b', 'c')]; -// const res = a.pipe(merge(b)); // $ExpectType Observable> -// }); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index aa7a75a94a..441e7b51f9 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, merge, race, zip, catchError, publish, publishLast, publishBehavior, share} from 'rxjs/operators'; +import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zip, catchError, publish, publishLast, publishBehavior, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -1090,13 +1090,13 @@ describe('Observable.lift', () => { expectObservable(result).toBe(expected); }); }); - it('should compose through merge', () => { + it('should compose through mergeWith', () => { rxTestScheduler.run(({ cold, expectObservable }) => { const e1 = cold(' -a--b-| '); const e2 = cold(' --x--y-|'); const expected = '-ax-by-|'; - const result = MyCustomObservable.from(e1).pipe(merge(e2, rxTestScheduler)); + const result = MyCustomObservable.from(e1).pipe(mergeWith(e2)); expect(result instanceof MyCustomObservable).to.be.true; diff --git a/spec/operators/merge-legacy-spec.ts b/spec/operators/merge-legacy-spec.ts deleted file mode 100644 index adeb9d5a60..0000000000 --- a/spec/operators/merge-legacy-spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { merge } from 'rxjs/operators'; -import { queueScheduler, of } from 'rxjs'; -import { expect } from 'chai'; - -describe('merge (legacy)', () => { - it('should merge an immediately-scheduled source with an immediately-scheduled second', (done) => { - const a = of(1, 2, 3, queueScheduler); - const b = of(4, 5, 6, 7, 8, queueScheduler); - const r = [1, 2, 4, 3, 5, 6, 7, 8]; - - a.pipe(merge(b, queueScheduler)).subscribe({ - next: (val) => { - expect(val).to.equal(r.shift()); - }, - error: (x) => { - done(new Error('should not be called')); - }, - complete: () => { - done(); - }, - }); - }); -}); diff --git a/src/internal/operators/merge.ts b/src/internal/operators/merge.ts deleted file mode 100644 index e5c921545b..0000000000 --- a/src/internal/operators/merge.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ObservableInput, ObservableInputTuple, OperatorFunction, SchedulerLike } from '../types'; -import { operate } from '../util/lift'; -import { argsOrArgArray } from '../util/argsOrArgArray'; -import { mergeAll } from './mergeAll'; -import { popNumber, popScheduler } from '../util/args'; -import { scheduled } from '../scheduled/scheduled'; -import { from } from '../observable/from'; - -/** @deprecated Replaced with {@link mergeWith}. Will be removed in v8. */ -export function merge(...sources: [...ObservableInputTuple]): OperatorFunction; -/** @deprecated Replaced with {@link mergeWith}. Will be removed in v8. */ -export function merge( - ...sourcesAndConcurrency: [...ObservableInputTuple, number] -): OperatorFunction; -/** @deprecated Replaced with {@link mergeWith}. Will be removed in v8. */ -export function merge( - ...sourcesAndScheduler: [...ObservableInputTuple, SchedulerLike] -): OperatorFunction; -/** @deprecated Replaced with {@link mergeWith}. Will be removed in v8. */ -export function merge( - ...sourcesAndConcurrencyAndScheduler: [...ObservableInputTuple, number, SchedulerLike] -): OperatorFunction; - -export function merge(...args: unknown[]): OperatorFunction { - const scheduler = popScheduler(args); - const concurrent = popNumber(args, Infinity); - args = argsOrArgArray(args); - - return operate((source, subscriber) => { - const sources = [source, ...(args as ObservableInput[])]; - mergeAll(concurrent)(scheduler ? scheduled(sources, scheduler) : from(sources)).subscribe(subscriber); - }); -} diff --git a/src/internal/operators/mergeWith.ts b/src/internal/operators/mergeWith.ts index b0c81426fb..4a84fbe58c 100644 --- a/src/internal/operators/mergeWith.ts +++ b/src/internal/operators/mergeWith.ts @@ -1,5 +1,7 @@ +import { from } from '../observable/from'; +import { mergeAll } from '../operators/mergeAll'; +import { operate } from '../util/lift'; import { ObservableInputTuple, OperatorFunction } from '../types'; -import { merge } from './merge'; /** * Merge the values from all observables to a single observable result. @@ -45,5 +47,7 @@ import { merge } from './merge'; export function mergeWith( ...otherSources: [...ObservableInputTuple] ): OperatorFunction { - return merge(...otherSources); + return operate((source, subscriber) => { + mergeAll()(from([source, ...otherSources])).subscribe(subscriber); + }); } diff --git a/src/operators/index.ts b/src/operators/index.ts index 1e95539e2c..e671ab910a 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -43,7 +43,6 @@ export { map } from '../internal/operators/map'; export { mapTo } from '../internal/operators/mapTo'; export { materialize } from '../internal/operators/materialize'; export { max } from '../internal/operators/max'; -export { merge } from '../internal/operators/merge'; export { mergeAll } from '../internal/operators/mergeAll'; export { mergeMap } from '../internal/operators/mergeMap'; export { mergeMapTo } from '../internal/operators/mergeMapTo'; From c617c27309fa5f18d06e79771b4babd5a2a4131f Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 00:44:44 +0200 Subject: [PATCH 02/15] feat(operator): removed deprecated `zip` operator BREAKING CHANGE: The `zip` operator is no longer available. Use `zipWith`. --- spec-dtslint/operators/zip-spec.ts | 25 ----- spec/Observable-spec.ts | 14 +-- spec/operators/publish-spec.ts | 11 +- spec/operators/zip-legacy-spec.ts | 172 ----------------------------- spec/operators/zip-spec.ts | 31 ------ src/internal/operators/zip.ts | 26 ----- src/internal/operators/zipWith.ts | 7 +- src/operators/index.ts | 1 - 8 files changed, 21 insertions(+), 266 deletions(-) delete mode 100644 spec-dtslint/operators/zip-spec.ts delete mode 100644 spec/operators/zip-legacy-spec.ts delete mode 100644 spec/operators/zip-spec.ts delete mode 100644 src/internal/operators/zip.ts diff --git a/spec-dtslint/operators/zip-spec.ts b/spec-dtslint/operators/zip-spec.ts deleted file mode 100644 index 111a355914..0000000000 --- a/spec-dtslint/operators/zip-spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { of } from 'rxjs'; -import { zip } from 'rxjs/operators'; - -it('should support observables', () => { - const o = of(1); // $ExpectType Observable - const a = o.pipe(zip(of(2))); // $ExpectType Observable<[number, number]> -}); - -it('should support rest parameter observables', () => { - const o = of(1); // $ExpectType Observable - const z = [of(2)]; // $ExpectType Observable[] - const a = o.pipe(zip(...z)); // $ExpectType Observable<[arg: number, ...rest: number[]]> -}); - -it('should support projected rest parameter observables', () => { - const o = of(1); // $ExpectType Observable - const z = [of(2)]; // $ExpectType Observable[] - const a = o.pipe(zip(...z, (...r) => r.map(v => v.toString()))); // $ExpectType Observable -}); - -it('should support projected arrays of observables', () => { - const o = of(1); // $ExpectType Observable - const z = [of(2)]; // $ExpectType Observable[] - const a = o.pipe(zip(z, (...r: any[]) => r.map(v => v.toString()))); // $ExpectType Observable -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index 441e7b51f9..69cb0bca20 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zip, catchError, publish, publishLast, publishBehavior, share} from 'rxjs/operators'; +import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, publishLast, publishBehavior, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -1124,21 +1124,21 @@ describe('Observable.lift', () => { }); }); - it('should compose through zip', () => { + it('should compose through zipWith', () => { rxTestScheduler.run(({ cold, expectObservable }) => { const e1 = cold(' -a--b-----c-d-e-|'); const e2 = cold(' --1--2-3-4---| '); const expected = '--A--B----C-D| '; - const result = MyCustomObservable.from(e1).pipe(zip(e2, (a, b) => String(a) + String(b))); + const result = MyCustomObservable.from(e1).pipe(zipWith(e2)); expect(result instanceof MyCustomObservable).to.be.true; expectObservable(result).toBe(expected, { - A: 'a1', - B: 'b2', - C: 'c3', - D: 'd4', + A: ['a', '1'], + B: ['b', '2'], + C: ['c', '3'], + D: ['d', '4'], }); }); }); diff --git a/spec/operators/publish-spec.ts b/spec/operators/publish-spec.ts index d953478a23..9e9f8dd52b 100644 --- a/spec/operators/publish-spec.ts +++ b/spec/operators/publish-spec.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { publish, zip, mergeMapTo, mergeMap, tap, refCount, retry, repeat } from 'rxjs/operators'; +import { publish, zipWith, mergeMapTo, mergeMap, map, tap, refCount, retry, repeat } from 'rxjs/operators'; import { ConnectableObservable, of, Subscription, Observable, pipe } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -75,7 +75,14 @@ describe('publish operator', () => { ' ----^-------!', ' --------^---!', ]; - const published = source.pipe(publish((x) => x.pipe(zip(x, (a, b) => (parseInt(a) + parseInt(b)).toString())))); + const published = source.pipe( + publish((x) => + x.pipe( + zipWith(x), + map(([a, b]) => (parseInt(a) + parseInt(b)).toString()) + ) + ) + ); const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); const expected1 = ' -2-4-6----8-|'; const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); diff --git a/spec/operators/zip-legacy-spec.ts b/spec/operators/zip-legacy-spec.ts deleted file mode 100644 index 2c5c0dd075..0000000000 --- a/spec/operators/zip-legacy-spec.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { expect } from 'chai'; -import { zip } from 'rxjs/operators'; -import { from } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** - * zip legacy still supports a mapping function, but it's deprecated - */ -describe('zip legacy', () => { - let rxTestScheduler: TestScheduler; - - beforeEach(() => { - rxTestScheduler = new TestScheduler(observableMatcher); - }); - - it('should zip the provided observables', (done) => { - const expected = ['a1', 'b2', 'c3']; - let i = 0; - - from(['a', 'b', 'c']) - .pipe(zip(from([1, 2, 3]), (a, b): string => a + b)) - .subscribe({ - next(x) { - expect(x).to.equal(expected[i++]); - }, - complete: done, - }); - }); - - it('should work with selector throws', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^-2---4----| '); - const asubs = ' ^-------! '; - const b = hot('---1-^--3----5----|'); - const bsubs = ' ^-------! '; - const expected = ' ---x----# '; - - const selector = (x: string, y: string) => { - if (y === '5') { - throw new Error('too bad'); - } else { - return x + y; - } - }; - const observable = a.pipe(zip(b, selector)); - expectObservable(observable).toBe(expected, { x: '23' }, new Error('too bad')); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should work with some data asymmetric 1', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|'); - const asubs = ' ^-----------------! '; - const b = hot('---1-^--2--4--6--8--0--| '); - const bsubs = ' ^-----------------! '; - const expected = ' ---a--b--c--d--e--| '; - - expectObservable( - a.pipe( - zip(b, (r1, r2) => { - return r1 + r2; - }) - ) - ).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should work with some data asymmetric 2', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^--2--4--6--8--0--| '); - const asubs = ' ^-----------------! '; - const b = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|'); - const bsubs = ' ^-----------------! '; - const expected = ' ---a--b--c--d--e--| '; - - expectObservable( - a.pipe( - zip(b, (r1, r2) => { - return r1 + r2; - }) - ) - ).toBe(expected, { a: '21', b: '43', c: '65', d: '87', e: '09' }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should work with some data symmetric', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^-1-3-5-7-9------| '); - const asubs = ' ^----------------! '; - const b = hot('---1-^--2--4--6--8--0--|'); - const bsubs = ' ^----------------! '; - const expected = ' ---a--b--c--d--e-| '; - - expectObservable( - a.pipe( - zip(b, (r1, r2) => { - return r1 + r2; - }) - ) - ).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should work with n-ary symmetric selector', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^-1----4----|'); - const asubs = ' ^---------! '; - const b = hot('---1-^--2--5----| '); - const bsubs = ' ^---------! '; - const c = hot('---1-^---3---6-| '); - const expected = ' ----x---y-| '; - - const observable = a.pipe( - zip(b, c, (r0, r1, r2) => { - return [r0, r1, r2]; - }) - ); - expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should work with n-ary symmetric array selector', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---1-^-1----4----|'); - const asubs = ' ^---------! '; - const b = hot('---1-^--2--5----| '); - const bsubs = ' ^---------! '; - const c = hot('---1-^---3---6-| '); - const expected = ' ----x---y-| '; - - const observable = a.pipe( - zip(b, c, (r0, r1, r2) => { - return [r0, r1, r2]; - }) - ); - expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); - - it('should combine two observables and selector', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot(' ---1---2---3---'); - const asubs = ' ^'; - const b = hot(' --4--5--6--7--8--'); - const bsubs = ' ^'; - const expected = '---x---y---z'; - - expectObservable( - a.pipe( - zip(b, (e1, e2) => { - return e1 + e2; - }) - ) - ).toBe(expected, { x: '14', y: '25', z: '36' }); - expectSubscriptions(a.subscriptions).toBe(asubs); - expectSubscriptions(b.subscriptions).toBe(bsubs); - }); - }); -}); diff --git a/spec/operators/zip-spec.ts b/spec/operators/zip-spec.ts deleted file mode 100644 index 1555d66305..0000000000 --- a/spec/operators/zip-spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { zip } from 'rxjs/operators'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {zip} */ -describe('zip', () => { - let rxTestScheduler: TestScheduler; - - beforeEach(() => { - rxTestScheduler = new TestScheduler(observableMatcher); - }); - - it('should work with non-empty observable and non-empty iterable selector that throws', () => { - rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const a = hot('---^--1--2--3--|'); - const asubs = ' ^-----!'; - const expected = '---x--#'; - const b = [4, 5, 6]; - - const selector = function (x: string, y: number) { - if (y === 5) { - throw new Error('too bad'); - } else { - return x + y; - } - }; - expectObservable(a.pipe(zip(b, selector))).toBe(expected, { x: '14' }, new Error('too bad')); - expectSubscriptions(a.subscriptions).toBe(asubs); - }); - }); -}); diff --git a/src/internal/operators/zip.ts b/src/internal/operators/zip.ts deleted file mode 100644 index f8c2f684ed..0000000000 --- a/src/internal/operators/zip.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { zip as zipStatic } from '../observable/zip'; -import { ObservableInput, ObservableInputTuple, OperatorFunction, Cons } from '../types'; -import { operate } from '../util/lift'; - -/** @deprecated Replaced with {@link zipWith}. Will be removed in v8. */ -export function zip(otherInputs: [...ObservableInputTuple]): OperatorFunction>; -/** @deprecated Replaced with {@link zipWith}. Will be removed in v8. */ -export function zip( - otherInputsAndProject: [...ObservableInputTuple], - project: (...values: Cons) => R -): OperatorFunction; -/** @deprecated Replaced with {@link zipWith}. Will be removed in v8. */ -export function zip(...otherInputs: [...ObservableInputTuple]): OperatorFunction>; -/** @deprecated Replaced with {@link zipWith}. Will be removed in v8. */ -export function zip( - ...otherInputsAndProject: [...ObservableInputTuple, (...values: Cons) => R] -): OperatorFunction; - -/** - * @deprecated Replaced with {@link zipWith}. Will be removed in v8. - */ -export function zip(...sources: Array | ((...values: Array) => R)>): OperatorFunction { - return operate((source, subscriber) => { - zipStatic(source as ObservableInput, ...(sources as Array>)).subscribe(subscriber); - }); -} diff --git a/src/internal/operators/zipWith.ts b/src/internal/operators/zipWith.ts index 22eaad7938..30a9bfbb22 100644 --- a/src/internal/operators/zipWith.ts +++ b/src/internal/operators/zipWith.ts @@ -1,5 +1,6 @@ import { ObservableInputTuple, OperatorFunction, Cons } from '../types'; -import { zip } from './zip'; +import { operate } from '../util/lift'; +import { zip } from '../observable/zip'; /** * Subscribes to the source, and the observable inputs provided as arguments, and combines their values, by index, into arrays. @@ -25,5 +26,7 @@ import { zip } from './zip'; * array. */ export function zipWith(...otherInputs: [...ObservableInputTuple]): OperatorFunction> { - return zip(...otherInputs); + return operate((source, subscriber) => { + zip<[T, ...A]>(source, ...otherInputs).subscribe(subscriber); + }); } diff --git a/src/operators/index.ts b/src/operators/index.ts index e671ab910a..f36e81c01c 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -103,6 +103,5 @@ export { windowTime } from '../internal/operators/windowTime'; export { windowToggle } from '../internal/operators/windowToggle'; export { windowWhen } from '../internal/operators/windowWhen'; export { withLatestFrom } from '../internal/operators/withLatestFrom'; -export { zip } from '../internal/operators/zip'; export { zipAll } from '../internal/operators/zipAll'; export { zipWith } from '../internal/operators/zipWith'; From 406cd8f74f3c1b70ae9b74b6f54d69ac4d4ca267 Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:01:48 +0200 Subject: [PATCH 03/15] feat(operator): removed deprecated `publishLast` operator BREAKING CHANGE: The `publishLast` operator is no longer available. Use `share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new AsyncSubject(), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publishlast). --- docs_app/content/guide/operators.md | 1 - .../images/marble-diagrams/publishLast.png | Bin 36269 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 3 - spec-dtslint/operators/publishLast-spec.ts | 10 - spec/Observable-spec.ts | 52 +-- .../multicasting-deprecations-spec.ts | 9 +- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/publishLast-spec.ts | 319 ------------------ src/index.ts | 1 - src/internal/operators/publishLast.ts | 76 ----- src/operators/index.ts | 1 - 13 files changed, 2 insertions(+), 473 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/publishLast.png delete mode 100644 spec-dtslint/operators/publishLast-spec.ts delete mode 100644 spec/operators/publishLast-spec.ts delete mode 100644 src/internal/operators/publishLast.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index c8d2551260..d160ece033 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -218,7 +218,6 @@ Also see the [Join Creation Operators](#join-creation-operators) section above. - [`multicast`](/api/operators/multicast) - [`publish`](/api/operators/publish) - [`publishBehavior`](/api/operators/publishBehavior) -- [`publishLast`](/api/operators/publishLast) - [`publishReplay`](/api/operators/publishReplay) - [`share`](/api/operators/share) diff --git a/docs_app/src/assets/images/marble-diagrams/publishLast.png b/docs_app/src/assets/images/marble-diagrams/publishLast.png deleted file mode 100644 index 854cd36c3d29d34ebcd14a32353d07430853e071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36269 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 { - const a = of(1, 2, 3).pipe(publishLast()); // $ExpectType Observable -}); - -it('should infer when type is specified', () => { - const a = of(1, 2, 3).pipe(publishLast()); // $ExpectType Observable -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index 69cb0bca20..2cf4999fc0 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, publishLast, publishBehavior, share} from 'rxjs/operators'; +import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, publishBehavior, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -814,34 +814,6 @@ describe('Observable.lift', () => { ); }); - - it('should compose through publishLast and refCount', (done) => { - const result = new MyCustomObservable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); - }).pipe( - publishLast(), - refCount(), - map((x) => 10 * x) - ); - - expect(result instanceof MyCustomObservable).to.be.true; - - const expected = [30]; - - result.subscribe( - { next: function (x) { - expect(x).to.equal(expected.shift()); - }, error: () => { - done(new Error('should not be called')); - }, complete: () => { - done(); - } } - ); - }); - it('should compose through publishBehavior and refCount', (done) => { const result = new MyCustomObservable((observer) => { observer.next(1); @@ -979,28 +951,6 @@ describe('Observable.lift', () => { expect(emitted).to.deep.equal([100, 200, 300]); }); - - it('should compose through publishLast and refCount, even if it is a Subject', () => { - const subject = new Subject(); - - const result = subject.pipe( - publishLast(), - refCount(), - map((x) => 10 * x) - ) as any as Subject; // Yes, this is correct. - - expect(result instanceof Subject).to.be.true; - - const emitted: any[] = []; - result.subscribe(value => emitted.push(value)); - - result.next(10); - result.next(20); - result.next(30); - - expect(emitted).to.deep.equal([100, 200, 300]); - }); - it('should compose through publishBehavior and refCount, even if it is a Subject', () => { const subject = new Subject(); diff --git a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts index d9024c44fc..c38bfef908 100644 --- a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts +++ b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts @@ -1,6 +1,6 @@ /** @prettier */ import { Observable, ConnectableObservable, connectable, of, AsyncSubject, BehaviorSubject, ReplaySubject, Subject, merge } from 'rxjs'; -import { connect, share, multicast, publish, publishReplay, publishBehavior, publishLast, refCount, repeat, retry } from 'rxjs/operators'; +import { connect, share, multicast, publish, publishReplay, publishBehavior, refCount, repeat, retry } from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -33,13 +33,6 @@ describe('multicasting equivalent tests', () => { (source) => source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) ); - testEquivalents( - 'publishLast(), refCount() and share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', - (source) => source.pipe(publishLast(), refCount()), - (source) => - source.pipe(share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) - ); - testEquivalents( 'publishBehavior("X"), refCount() and share({ connector: () => new BehaviorSubject("X"), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', (source) => source.pipe(publishBehavior('X'), refCount()), diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 551bd5e996..0d20129b18 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -132,7 +132,6 @@ describe('index', () => { expect(index.pluck).to.exist; expect(index.publish).to.exist; expect(index.publishBehavior).to.exist; - expect(index.publishLast).to.exist; expect(index.publishReplay).to.exist; expect(index.raceWith).to.exist; expect(index.reduce).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index fcfa639eef..ec808ee2aa 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -56,7 +56,6 @@ describe('operators/index', () => { expect(index.pluck).to.exist; expect(index.publish).to.exist; expect(index.publishBehavior).to.exist; - expect(index.publishLast).to.exist; expect(index.publishReplay).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; diff --git a/spec/operators/publishLast-spec.ts b/spec/operators/publishLast-spec.ts deleted file mode 100644 index 5d9122c6b6..0000000000 --- a/spec/operators/publishLast-spec.ts +++ /dev/null @@ -1,319 +0,0 @@ -import { expect } from 'chai'; -import { publishLast, mergeMapTo, tap, mergeMap, refCount, retry } from 'rxjs/operators'; -import { ConnectableObservable, of, Subscription, Observable, pipe } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {publishLast} */ -describe('publishLast operator', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should emit last notification of a simple source Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-| '); - const sourceSubs = ' ^--------------! '; - const published = source.pipe(publishLast()) as ConnectableObservable; - const expected = ' ---------------(5|)'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should return a ConnectableObservable-ish', () => { - const source = of(1).pipe(publishLast()) as ConnectableObservable; - expect(typeof (source)._subscribe === 'function').to.be.true; - expect(typeof (source).getSubject === 'function').to.be.true; - expect(typeof source.connect === 'function').to.be.true; - expect(typeof source.refCount === 'function').to.be.true; - }); - - it('should do nothing if connect is not called, despite subscriptions', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs: string[] = []; - const published = source.pipe(publishLast()); - const expected = ' - '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should multicast the same values to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-| '); - const sourceSubs = ' ^-----------! '; - const published = source.pipe(publishLast()) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' ------------(4|)'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ------------(4|)'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ------------(4|)'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast an error from the source to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishLast()) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' ------------#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ------------#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ------------#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should not cast any values to multiple observers, when source is unsubscribed explicitly and early', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe(publishLast()) as ConnectableObservable; - const unsub = ' ---------u '; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' ---------- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ---------- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ---------- '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - it('should not break unsubscription chains when result is unsubscribed explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe( - mergeMap((x) => of(x)), - publishLast() - ) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' ---------- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ---------- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ---------- '; - const unsub = ' ---------u '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - describe('with refCount()', () => { - it('should connect when first subscriber subscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^-----------!'; - const replayed = source.pipe(publishLast(), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const expected1 = ' ---------------(4|)'; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const expected2 = ' ---------------(4|)'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(replayed)); - const expected3 = ' ---------------(4|)'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should disconnect when last subscriber unsubscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^--------! '; - const replayed = source.pipe(publishLast(), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const unsub1 = ' ----------! '; - const expected1 = ' ----------- '; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const unsub2 = ' ------------! '; - const expected2 = ' ------------- '; - - expectObservable(subscriber1, unsub1).toBe(expected1); - expectObservable(subscriber2, unsub2).toBe(expected2); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be retryable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishLast(), refCount(), retry(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' ------------#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ------------#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ------------#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - }); - - it('should multicast an empty source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('| '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishLast()) as ConnectableObservable; - const expected = ' | '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a never source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('-'); - const sourceSubs = ' ^'; - const published = source.pipe(publishLast()) as ConnectableObservable; - const expected = ' -'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a throw source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('# '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishLast()) as ConnectableObservable; - const expected = ' # '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast one observable to multiple observers', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishLast()) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([4]); - expect(results2).to.deep.equal([4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should be referentially-transparent', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source1 = cold('-1-2-3-4-5-| '); - const source1Subs = ' ^----------! '; - const expected1 = ' -----------(5|)'; - const source2 = cold('-6-7-8-9-0-| '); - const source2Subs = ' ^----------! '; - const expected2 = ' -----------(0|)'; - - // Calls to the _operator_ must be referentially-transparent. - const partialPipeLine = pipe(publishLast()); - - // The non-referentially-transparent publishing occurs within the _operator function_ - // returned by the _operator_ and that happens when the complete pipeline is composed. - const published1 = source1.pipe(partialPipeLine) as ConnectableObservable; - const published2 = source2.pipe(partialPipeLine) as ConnectableObservable; - - expectObservable(published1).toBe(expected1); - expectSubscriptions(source1.subscriptions).toBe(source1Subs); - expectObservable(published2).toBe(expected2); - expectSubscriptions(source2.subscriptions).toBe(source2Subs); - - published1.connect(); - published2.connect(); - }); - }); -}); diff --git a/src/index.ts b/src/index.ts index 713a6129f1..c9a29201d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -152,7 +152,6 @@ export { pairwise } from './internal/operators/pairwise'; export { pluck } from './internal/operators/pluck'; export { publish } from './internal/operators/publish'; export { publishBehavior } from './internal/operators/publishBehavior'; -export { publishLast } from './internal/operators/publishLast'; export { publishReplay } from './internal/operators/publishReplay'; export { raceWith } from './internal/operators/raceWith'; export { reduce } from './internal/operators/reduce'; diff --git a/src/internal/operators/publishLast.ts b/src/internal/operators/publishLast.ts deleted file mode 100644 index ded47fb523..0000000000 --- a/src/internal/operators/publishLast.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Observable } from '../Observable'; -import { AsyncSubject } from '../AsyncSubject'; -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { UnaryFunction } from '../types'; - -/** - * Returns a connectable observable sequence that shares a single subscription to the - * underlying sequence containing only the last notification. - * - * ![](publishLast.png) - * - * Similar to {@link publish}, but it waits until the source observable completes and stores - * the last emitted value. - * Similarly to {@link publishReplay} and {@link publishBehavior}, this keeps storing the last - * value even if it has no more subscribers. If subsequent subscriptions happen, they will - * immediately get that last stored value and complete. - * - * ## Example - * - * ```ts - * import { ConnectableObservable, interval, publishLast, tap, take } from 'rxjs'; - * - * const connectable = >interval(1000) - * .pipe( - * tap(x => console.log('side effect', x)), - * take(3), - * publishLast() - * ); - * - * connectable.subscribe({ - * next: x => console.log('Sub. A', x), - * error: err => console.log('Sub. A Error', err), - * complete: () => console.log('Sub. A Complete') - * }); - * - * connectable.subscribe({ - * next: x => console.log('Sub. B', x), - * error: err => console.log('Sub. B Error', err), - * complete: () => console.log('Sub. B Complete') - * }); - * - * connectable.connect(); - * - * // Results: - * // 'side effect 0' - after one second - * // 'side effect 1' - after two seconds - * // 'side effect 2' - after three seconds - * // 'Sub. A 2' - immediately after 'side effect 2' - * // 'Sub. B 2' - * // 'Sub. A Complete' - * // 'Sub. B Complete' - * ``` - * - * @see {@link ConnectableObservable} - * @see {@link publish} - * @see {@link publishReplay} - * @see {@link publishBehavior} - * - * @return A function that returns an Observable that emits elements of a - * sequence produced by multicasting the source sequence. - * @deprecated Will be removed in v8. To create a connectable observable with an - * {@link AsyncSubject} under the hood, use {@link connectable}. - * `source.pipe(publishLast())` is equivalent to - * `connectable(source, { connector: () => new AsyncSubject(), resetOnDisconnect: false })`. - * If you're using {@link refCount} after `publishLast`, use the {@link share} operator instead. - * `source.pipe(publishLast(), refCount())` is equivalent to - * `source.pipe(share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }))`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishLast(): UnaryFunction, ConnectableObservable> { - // Note that this has *never* supported a selector function like `publish` and `publishReplay`. - return (source) => { - const subject = new AsyncSubject(); - return new ConnectableObservable(source, () => subject); - }; -} diff --git a/src/operators/index.ts b/src/operators/index.ts index f36e81c01c..2c94265225 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -57,7 +57,6 @@ export { partition } from '../internal/operators/partition'; export { pluck } from '../internal/operators/pluck'; export { publish } from '../internal/operators/publish'; export { publishBehavior } from '../internal/operators/publishBehavior'; -export { publishLast } from '../internal/operators/publishLast'; export { publishReplay } from '../internal/operators/publishReplay'; export { race } from '../internal/operators/race'; export { raceWith } from '../internal/operators/raceWith'; From d38037bbd95fde103a5cbe2c6f4a89183503dd6c Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:19:26 +0200 Subject: [PATCH 04/15] feat(operator): removed deprecated `publishReplay` operator BREAKING CHANGE: The `publishReplay` operator is no longer available. Use `share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new ReplaySubject(1), resetOnDisconnect: false })` [Multicasting](https://rxjs.dev/deprecations/multicasting#publishreplay). --- docs_app/content/guide/operators.md | 1 - docs_app/content/guide/scheduler.md | 4 +- .../images/marble-diagrams/publishReplay.png | Bin 49691 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 3 - spec-dtslint/operators/publishReplay-spec.ts | 46 -- .../multicasting-deprecations-spec.ts | 20 +- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/publishReplay-spec.ts | 561 ------------------ spec/operators/refCount-spec.ts | 43 +- src/index.ts | 1 - src/internal/operators/publishReplay.ts | 96 --- src/internal/operators/shareReplay.ts | 1 - src/operators/index.ts | 1 - 15 files changed, 5 insertions(+), 775 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/publishReplay.png delete mode 100644 spec-dtslint/operators/publishReplay-spec.ts delete mode 100644 spec/operators/publishReplay-spec.ts delete mode 100644 src/internal/operators/publishReplay.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index d160ece033..c8bfcc4d97 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -218,7 +218,6 @@ Also see the [Join Creation Operators](#join-creation-operators) section above. - [`multicast`](/api/operators/multicast) - [`publish`](/api/operators/publish) - [`publishBehavior`](/api/operators/publishBehavior) -- [`publishReplay`](/api/operators/publishReplay) - [`share`](/api/operators/share) ### Error Handling Operators diff --git a/docs_app/content/guide/scheduler.md b/docs_app/content/guide/scheduler.md index 4496e13d5c..22d76b473c 100644 --- a/docs_app/content/guide/scheduler.md +++ b/docs_app/content/guide/scheduler.md @@ -144,6 +144,6 @@ Because RxJS uses the least concurrency scheduler, you can pick a different sche Time-related operators like `bufferTime`, `debounceTime`, `delay`, `auditTime`, `sampleTime`, `throttleTime`, `timeInterval`, `timeout`, `timeoutWith`, `windowTime` all take a Scheduler as the last argument, and otherwise operate by default on the `asyncScheduler`. -Other instance operators that take a Scheduler as argument: `cache`, `combineLatest`, `concat`, `expand`, `merge`, `publishReplay`, `startWith`. +Other instance operators that take a Scheduler as argument: `cache`, `combineLatest`, `concat`, `expand`, `merge`, `startWith`. -Notice that both `cache` and `publishReplay` accept a Scheduler because they utilize a ReplaySubject. The constructor of a ReplaySubjects takes an optional Scheduler as the last argument because ReplaySubject may deal with time, which only makes sense in the context of a Scheduler. By default, a ReplaySubject uses the `queueScheduler` Scheduler to provide a clock. +Notice that `cache` accept a Scheduler because they utilize a ReplaySubject. The constructor of a ReplaySubjects takes an optional Scheduler as the last argument because ReplaySubject may deal with time, which only makes sense in the context of a Scheduler. By default, a ReplaySubject uses the `queueScheduler` Scheduler to provide a clock. diff --git a/docs_app/src/assets/images/marble-diagrams/publishReplay.png b/docs_app/src/assets/images/marble-diagrams/publishReplay.png deleted file mode 100644 index d694f4b902fa2c2a745998cb7052d19e4449a996..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49691 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 diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index 194d1f0655..ff7e6808e6 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -68,7 +68,6 @@ export type ApiUnion = | 'pluck' | 'publish' | 'publishBehavior' - | 'publishReplay' | 'race' | 'range' | 'reduce' diff --git a/docs_app/tools/decision-tree-generator/src/tree.yml b/docs_app/tools/decision-tree-generator/src/tree.yml index 20b6d256ef..8575492591 100644 --- a/docs_app/tools/decision-tree-generator/src/tree.yml +++ b/docs_app/tools/decision-tree-generator/src/tree.yml @@ -259,9 +259,6 @@ - label: using a BehaviorSubject children: - label: publishBehavior - - label: using a ReplaySubject - children: - - label: publishReplay - label: using a specific subject implementation children: - label: multicast diff --git a/spec-dtslint/operators/publishReplay-spec.ts b/spec-dtslint/operators/publishReplay-spec.ts deleted file mode 100644 index 943aed4056..0000000000 --- a/spec-dtslint/operators/publishReplay-spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { of, asyncScheduler, Observable } from 'rxjs'; -import { publishReplay } from 'rxjs/operators'; - -it('should accept empty parameter', () => { - const a = of(1, 2, 3).pipe(publishReplay()); // $ExpectType Observable -}); - -it('should accept bufferSize parameter only', () => { - const a = of(1, 2, 3).pipe(publishReplay(1)); // $ExpectType Observable -}); - -it('should accept windowTime and bufferSize', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1)); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, scheduler', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, asyncScheduler)); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector of OperatorFunction', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, (x) => of('a'))); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector returning union type', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, () => Math.random() > 0.5 ? of(123) : of('test'))); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector of MonoTypeOperatorFunction', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, (x) => x)); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector returning union type, and a scheduler', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, () => Math.random() > 0.5 ? of(123) : of('test'), asyncScheduler)); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector of OperatorFunction, and scheduler', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, (x) => of('a'), asyncScheduler)); // $ExpectType Observable -}); - -it('should accept windowTime, bufferSize, selector of MonoTypeOperatorFunction, and scheduler', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, (x) => x, asyncScheduler)); // $ExpectType Observable -}); - -it('should enforce type on selector', () => { - const a = of(1, 2, 3).pipe(publishReplay(1, 1, (x: Observable) => x)); // $ExpectError -}); diff --git a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts index c38bfef908..3f5b1b1114 100644 --- a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts +++ b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts @@ -1,6 +1,6 @@ /** @prettier */ import { Observable, ConnectableObservable, connectable, of, AsyncSubject, BehaviorSubject, ReplaySubject, Subject, merge } from 'rxjs'; -import { connect, share, multicast, publish, publishReplay, publishBehavior, refCount, repeat, retry } from 'rxjs/operators'; +import { connect, share, multicast, publish, publishBehavior, refCount, repeat, retry } from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -42,15 +42,6 @@ describe('multicasting equivalent tests', () => { ) ); - testEquivalents( - 'publishReplay(3, 10), refCount() and share({ connector: () => new ReplaySubject(3, 10), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', - (source) => source.pipe(publishReplay(3, 10), refCount()), - (source) => - source.pipe( - share({ connector: () => new ReplaySubject(3, 10), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }) - ) - ); - const fn = (source: Observable) => merge(source, source); testEquivalents( @@ -59,15 +50,6 @@ describe('multicasting equivalent tests', () => { (source) => source.pipe(connect(fn)) ); - testEquivalents( - 'publishReplay(3, 10, fn) and `subject = new ReplaySubject(3, 10), connect({ connector: () => subject , setup: fn })`', - (source) => source.pipe(publishReplay(3, 10, fn)), - (source) => { - const subject = new ReplaySubject(3, 10); - return source.pipe(connect(fn, { connector: () => subject })); - } - ); - /** * Used to test a variety of scenarios with multicast operators that should be equivalent. * @param name The name to add to the test output diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 0d20129b18..4070478b87 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -132,7 +132,6 @@ describe('index', () => { expect(index.pluck).to.exist; expect(index.publish).to.exist; expect(index.publishBehavior).to.exist; - expect(index.publishReplay).to.exist; expect(index.raceWith).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index ec808ee2aa..7344f475cf 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -56,7 +56,6 @@ describe('operators/index', () => { expect(index.pluck).to.exist; expect(index.publish).to.exist; expect(index.publishBehavior).to.exist; - expect(index.publishReplay).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; expect(index.repeatWhen).to.exist; diff --git a/spec/operators/publishReplay-spec.ts b/spec/operators/publishReplay-spec.ts deleted file mode 100644 index 52fb8fa465..0000000000 --- a/spec/operators/publishReplay-spec.ts +++ /dev/null @@ -1,561 +0,0 @@ -import { expect } from 'chai'; -import { throwError, ConnectableObservable, EMPTY, NEVER, of, Observable, Subscription, pipe } from 'rxjs'; -import { publishReplay, mergeMapTo, tap, mergeMap, refCount, retry, repeat, map } from 'rxjs/operators'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {publishReplay} */ -describe('publishReplay operator', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should mirror a simple source Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs = ' ^--------------!'; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const expected = ' --1-2---3-4--5-|'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should return a ConnectableObservable-ish', () => { - const source = of(1).pipe(publishReplay()) as ConnectableObservable; - expect(typeof (source)._subscribe === 'function').to.be.true; - expect(typeof (source).getSubject === 'function').to.be.true; - expect(typeof source.connect === 'function').to.be.true; - expect(typeof source.refCount === 'function').to.be.true; - }); - - it('should do nothing if connect is not called, despite subscriptions', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs: string[] = []; - const published = source.pipe(publishReplay(1)); - const expected = ' -'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should multicast the same values to multiple observers, bufferSize=1', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast the same values to multiple observers, bufferSize=2', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-----3------4-|'); - const sourceSubs = ' ^-----------------!'; - const published = source.pipe(publishReplay(2)) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-----3------4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----(12)-3------4-|'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(published)); - const expected3 = ' -----------(23)-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast an error from the source to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast the same values to multiple observers, but is unsubscribed explicitly and early', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const unsub = ' ---------u '; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3- '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - it('should not break unsubscription chains when result is unsubscribed explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe( - mergeMap((x) => of(x)), - publishReplay(1) - ) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3- '; - const unsub = ' ---------u '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - describe('with refCount()', () => { - it('should connect when first subscriber subscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^-----------!'; - const replayed = source.pipe(publishReplay(1), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const expected1 = ' ----1-2-3----4-|'; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const expected2 = ' -------23----4-|'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(replayed)); - const expected3 = ' -----------3-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should disconnect when last subscriber unsubscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^--------! '; - const replayed = source.pipe(publishReplay(1), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const unsub1 = ' ----------! '; - const expected1 = ' ----1-2-3-- '; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const unsub2 = ' ------------! '; - const expected2 = ' -------23---- '; - - expectObservable(subscriber1, unsub1).toBe(expected1); - expectObservable(subscriber2, unsub2).toBe(expected2); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be retryable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-# '); - const sourceSubs = ' ^-----------! '; - const published = source.pipe(publishReplay(1), refCount(), retry(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-(444#)'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-(444#)'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-(444#)'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be repeatable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-| '); - const sourceSubs = ' ^-----------! '; - const published = source.pipe(publishReplay(1), refCount(), repeat(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-(44|)'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-(44|)'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-(44|)'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - }); - - it('should multicast one observable to multiple observers', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishReplay()) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([1, 2, 3, 4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should replay as many events as specified by the bufferSize', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishReplay(2)) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([3, 4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should emit replayed values and resubscribe to the source when reconnected without source completion', () => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - // observer.complete(); - }); - - const connectable = source.pipe(publishReplay(2)) as ConnectableObservable; - const subscription1 = connectable.subscribe((x) => { - results1.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect().unsubscribe(); - subscription1.unsubscribe(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([]); - expect(subscriptions).to.equal(1); - - const subscription2 = connectable.subscribe((x) => { - results2.push(x); - }); - - connectable.connect().unsubscribe(); - subscription2.unsubscribe(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([3, 4, 1, 2, 3, 4]); - expect(subscriptions).to.equal(2); - }); - - it('should emit replayed values plus completed when subscribed after completed', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishReplay(2)) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([]); - expect(subscriptions).to.equal(1); - - connectable.subscribe({ - next: (x) => { - results2.push(x); - }, - error: (x) => { - done(new Error('should not be called')); - }, - complete: () => { - expect(results2).to.deep.equal([3, 4]); - done(); - }, - }); - }); - - it('should multicast an empty source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('| '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const expected = ' |'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a never source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('-'); - const sourceSubs = ' ^'; - - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const expected = ' -'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a throw source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('# '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishReplay(1)) as ConnectableObservable; - const expected = ' # '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should mirror a simple source Observable with selector', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const values = { a: 2, b: 4, c: 6, d: 8 }; - const selector = (observable: Observable) => observable.pipe(map((v) => 2 * +v)); - const source = cold('--1-2---3-4---|'); - const sourceSubs = ' ^-------------!'; - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' --a-b---c-d---|'; - - expectObservable(published).toBe(expected, values); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should EMIT an error when the selector throws an exception', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const error = "It's broken"; - const selector = () => { - throw error; - }; - const source = cold('--1-2---3-4---|'); - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' # '; - - expectObservable(published).toBe(expected, undefined, "It's broken"); - }); - }); - - it('should emit an error when the selector returns an Observable that emits an error', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const error = "It's broken"; - const innerObservable = cold('--5-6----#', undefined, error); - const selector = (observable: Observable) => observable.pipe(mergeMapTo(innerObservable)); - const source = cold('--1--2---3---|'); - const sourceSubs = ' ^----------! '; - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' ----5-65-6-# '; - - expectObservable(published).toBe(expected, undefined, error); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should terminate immediately when the selector returns an empty Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const selector = () => EMPTY; - const source = cold('--1--2---3---|'); - const sourceSubs = ' (^!) '; - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' | '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should not emit and should not complete/error when the selector returns never', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const selector = () => NEVER; - const source = cold('-'); - const sourceSubs = ' ^'; - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' -'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should emit error when the selector returns Observable.throw', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const error = "It's broken"; - const selector = () => throwError(() => error); - const source = cold('--1--2---3---|'); - const sourceSubs = ' (^!) '; - const published = source.pipe(publishReplay(1, Infinity, selector)); - const expected = ' # '; - - expectObservable(published).toBe(expected, undefined, error); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should be referentially-transparent', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source1 = cold('-1-2-3-4-5-|'); - const source1Subs = ' ^----------!'; - const expected1 = ' -1-2-3-4-5-|'; - const source2 = cold('-6-7-8-9-0-|'); - const source2Subs = ' ^----------!'; - const expected2 = ' -6-7-8-9-0-|'; - - // Calls to the _operator_ must be referentially-transparent. - const partialPipeLine = pipe(publishReplay(1)); - - // The non-referentially-transparent publishing occurs within the _operator function_ - // returned by the _operator_ and that happens when the complete pipeline is composed. - const published1 = source1.pipe(partialPipeLine) as ConnectableObservable; - const published2 = source2.pipe(partialPipeLine) as ConnectableObservable; - - expectObservable(published1).toBe(expected1); - expectSubscriptions(source1.subscriptions).toBe(source1Subs); - expectObservable(published2).toBe(expected2); - expectSubscriptions(source2.subscriptions).toBe(source2Subs); - - published1.connect(); - published2.connect(); - }); - }); -}); diff --git a/spec/operators/refCount-spec.ts b/spec/operators/refCount-spec.ts index 50cad7fd89..686043f2bb 100644 --- a/spec/operators/refCount-spec.ts +++ b/spec/operators/refCount-spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { TestScheduler } from 'rxjs/testing'; -import { refCount, publish, publishReplay, first } from 'rxjs/operators'; -import { NEVER, noop, Observable, Subject } from 'rxjs'; +import { refCount, publish } from 'rxjs/operators'; +import { NEVER, noop, Observable } from 'rxjs'; import { observableMatcher } from '../helpers/observableMatcher'; /** @test {refCount} */ @@ -71,43 +71,4 @@ describe('refCount', () => { expect(unsubscribeCalled).to.be.true; done(); }); - - it('should not unsubscribe when a subscriber synchronously unsubscribes if other subscribers are present', () => { - let unsubscribeCalled = false; - const connectable = new Observable((observer) => { - observer.next(true); - return () => { - unsubscribeCalled = true; - }; - }).pipe(publishReplay(1)); - - const refCounted = connectable.pipe(refCount()); - - refCounted.subscribe(); - refCounted.subscribe().unsubscribe(); - - expect((connectable as any)._refCount).to.equal(1); - expect(unsubscribeCalled).to.be.false; - }); - - it('should not unsubscribe when a subscriber synchronously unsubscribes if other subscribers are present and the source is a Subject', () => { - const arr: string[] = []; - const subject = new Subject(); - const connectable = subject.pipe(publishReplay(1)); - const refCounted = connectable.pipe(refCount()); - - refCounted.subscribe((val) => { - arr.push(val); - }); - - subject.next('the number one'); - - refCounted.pipe(first()).subscribe().unsubscribe(); - - subject.next('the number two'); - - expect((connectable as any)._refCount).to.equal(1); - expect(arr[0]).to.equal('the number one'); - expect(arr[1]).to.equal('the number two'); - }); }); diff --git a/src/index.ts b/src/index.ts index c9a29201d2..b073cd51a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -152,7 +152,6 @@ export { pairwise } from './internal/operators/pairwise'; export { pluck } from './internal/operators/pluck'; export { publish } from './internal/operators/publish'; export { publishBehavior } from './internal/operators/publishBehavior'; -export { publishReplay } from './internal/operators/publishReplay'; export { raceWith } from './internal/operators/raceWith'; export { reduce } from './internal/operators/reduce'; export { repeat, RepeatConfig } from './internal/operators/repeat'; diff --git a/src/internal/operators/publishReplay.ts b/src/internal/operators/publishReplay.ts deleted file mode 100644 index 47494e2a66..0000000000 --- a/src/internal/operators/publishReplay.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Observable } from '../Observable'; -import { ReplaySubject } from '../ReplaySubject'; -import { multicast } from './multicast'; -import { MonoTypeOperatorFunction, OperatorFunction, TimestampProvider, ObservableInput, ObservedValueOf } from '../types'; -import { isFunction } from '../util/isFunction'; - -/** - * Creates a {@link ConnectableObservable} that uses a {@link ReplaySubject} - * internally. - * - * @param bufferSize The buffer size for the underlying {@link ReplaySubject}. - * @param windowTime The window time for the underlying {@link ReplaySubject}. - * @param timestampProvider The timestamp provider for the underlying {@link ReplaySubject}. - * @deprecated Will be removed in v8. To create a connectable observable that uses a - * {@link ReplaySubject} under the hood, use {@link connectable}. - * `source.pipe(publishReplay(size, time, scheduler))` is equivalent to - * `connectable(source, { connector: () => new ReplaySubject(size, time, scheduler), resetOnDisconnect: false })`. - * If you're using {@link refCount} after `publishReplay`, use the {@link share} operator instead. - * `publishReplay(size, time, scheduler), refCount()` is equivalent to - * `share({ connector: () => new ReplaySubject(size, time, scheduler), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishReplay( - bufferSize?: number, - windowTime?: number, - timestampProvider?: TimestampProvider -): MonoTypeOperatorFunction; - -/** - * Creates an observable, that when subscribed to, will create a {@link ReplaySubject}, - * and pass an observable from it (using [asObservable](api/index/class/Subject#asObservable)) to - * the `selector` function, which then returns an observable that is subscribed to before - * "connecting" the source to the internal `ReplaySubject`. - * - * Since this is deprecated, for additional details see the documentation for {@link connect}. - * - * @param bufferSize The buffer size for the underlying {@link ReplaySubject}. - * @param windowTime The window time for the underlying {@link ReplaySubject}. - * @param selector A function used to setup the multicast. - * @param timestampProvider The timestamp provider for the underlying {@link ReplaySubject}. - * @deprecated Will be removed in v8. Use the {@link connect} operator instead. - * `source.pipe(publishReplay(size, window, selector, scheduler))` is equivalent to - * `source.pipe(connect(selector, { connector: () => new ReplaySubject(size, window, scheduler) }))`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishReplay>( - bufferSize: number | undefined, - windowTime: number | undefined, - selector: (shared: Observable) => O, - timestampProvider?: TimestampProvider -): OperatorFunction>; - -/** - * Creates a {@link ConnectableObservable} that uses a {@link ReplaySubject} - * internally. - * - * @param bufferSize The buffer size for the underlying {@link ReplaySubject}. - * @param windowTime The window time for the underlying {@link ReplaySubject}. - * @param selector Passing `undefined` here determines that this operator will return a {@link ConnectableObservable}. - * @param timestampProvider The timestamp provider for the underlying {@link ReplaySubject}. - * @deprecated Will be removed in v8. To create a connectable observable that uses a - * {@link ReplaySubject} under the hood, use {@link connectable}. - * `source.pipe(publishReplay(size, time, scheduler))` is equivalent to - * `connectable(source, { connector: () => new ReplaySubject(size, time, scheduler), resetOnDisconnect: false })`. - * If you're using {@link refCount} after `publishReplay`, use the {@link share} operator instead. - * `publishReplay(size, time, scheduler), refCount()` is equivalent to - * `share({ connector: () => new ReplaySubject(size, time, scheduler), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishReplay>( - bufferSize: number | undefined, - windowTime: number | undefined, - selector: undefined, - timestampProvider: TimestampProvider -): OperatorFunction>; - -/** - * @deprecated Will be removed in v8. Use the {@link connectable} observable, the {@link connect} operator or the - * {@link share} operator instead. See the overloads below for equivalent replacement examples of this operator's - * behaviors. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishReplay( - bufferSize?: number, - windowTime?: number, - selectorOrScheduler?: TimestampProvider | OperatorFunction, - timestampProvider?: TimestampProvider -) { - if (selectorOrScheduler && !isFunction(selectorOrScheduler)) { - timestampProvider = selectorOrScheduler; - } - const selector = isFunction(selectorOrScheduler) ? selectorOrScheduler : undefined; - // Note, we're passing `selector!` here, because at runtime, `undefined` is an acceptable argument - // but it makes our TypeScript signature for `multicast` unhappy (as it should, because it's gross). - return (source: Observable) => multicast(new ReplaySubject(bufferSize, windowTime, timestampProvider), selector!)(source); -} diff --git a/src/internal/operators/shareReplay.ts b/src/internal/operators/shareReplay.ts index b43f363e92..96d6e0c4dc 100644 --- a/src/internal/operators/shareReplay.ts +++ b/src/internal/operators/shareReplay.ts @@ -141,7 +141,6 @@ export function shareReplay(bufferSize?: number, windowTime?: number, schedul * * @see {@link publish} * @see {@link share} - * @see {@link publishReplay} * * @param configOrBufferSize Maximum element count of the replay buffer or {@link ShareReplayConfig configuration} * object. diff --git a/src/operators/index.ts b/src/operators/index.ts index 2c94265225..13d1d67537 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -57,7 +57,6 @@ export { partition } from '../internal/operators/partition'; export { pluck } from '../internal/operators/pluck'; export { publish } from '../internal/operators/publish'; export { publishBehavior } from '../internal/operators/publishBehavior'; -export { publishReplay } from '../internal/operators/publishReplay'; export { race } from '../internal/operators/race'; export { raceWith } from '../internal/operators/raceWith'; export { reduce } from '../internal/operators/reduce'; From 3d5d65d1a197831e72ee08bdf574caf4ad27fb3f Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:23:09 +0200 Subject: [PATCH 05/15] feat(operator): removed deprecated `publishBehavior` operator BREAKING CHANGE: The `publishBehavior` operator is no longer available. Use `share({ connector: () => new BehaviorSubject(0), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new BehaviorSubject(0), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publishbehavior). --- docs_app/content/guide/operators.md | 1 - .../marble-diagrams/publishBehavior.png | Bin 53373 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 3 - .../operators/publishBehavior-spec.ts | 14 - spec/Observable-spec.ts | 49 +-- .../multicasting-deprecations-spec.ts | 11 +- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/publishBehavior-spec.ts | 404 ------------------ src/index.ts | 1 - src/internal/operators/publishBehavior.ts | 26 -- src/operators/index.ts | 1 - 13 files changed, 2 insertions(+), 511 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/publishBehavior.png delete mode 100644 spec-dtslint/operators/publishBehavior-spec.ts delete mode 100644 spec/operators/publishBehavior-spec.ts delete mode 100644 src/internal/operators/publishBehavior.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index c8bfcc4d97..fa26226e85 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -217,7 +217,6 @@ Also see the [Join Creation Operators](#join-creation-operators) section above. - [`multicast`](/api/operators/multicast) - [`publish`](/api/operators/publish) -- [`publishBehavior`](/api/operators/publishBehavior) - [`share`](/api/operators/share) ### Error Handling Operators diff --git a/docs_app/src/assets/images/marble-diagrams/publishBehavior.png b/docs_app/src/assets/images/marble-diagrams/publishBehavior.png deleted file mode 100644 index 9f8988c6d45654267c19de733285b254fdebdae2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53373 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 IK6?4T0OW*9M*si- diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index ff7e6808e6..8d1ca885c4 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -67,7 +67,6 @@ export type ApiUnion = | 'pipe' | 'pluck' | 'publish' - | 'publishBehavior' | 'race' | 'range' | 'reduce' diff --git a/docs_app/tools/decision-tree-generator/src/tree.yml b/docs_app/tools/decision-tree-generator/src/tree.yml index 8575492591..fa5e47ca4e 100644 --- a/docs_app/tools/decision-tree-generator/src/tree.yml +++ b/docs_app/tools/decision-tree-generator/src/tree.yml @@ -256,9 +256,6 @@ - label: and start it manually or imperatively children: - label: publish - - label: using a BehaviorSubject - children: - - label: publishBehavior - label: using a specific subject implementation children: - label: multicast diff --git a/spec-dtslint/operators/publishBehavior-spec.ts b/spec-dtslint/operators/publishBehavior-spec.ts deleted file mode 100644 index 54130a9f9b..0000000000 --- a/spec-dtslint/operators/publishBehavior-spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { of } from 'rxjs'; -import { publishBehavior } from 'rxjs/operators'; - -it('should enforce parameter', () => { - const a = of(1, 2, 3).pipe(publishBehavior()); // $ExpectError -}); - -it('should infer correctly with parameter', () => { - const a = of(1, 2, 3).pipe(publishBehavior(4)); // $ExpectType Observable -}); - -it('should enforce type on parameter', () => { - const a = of(1, 2, 3).pipe(publishBehavior('a')); // $ExpectError -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index 2cf4999fc0..e109363b67 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, publishBehavior, share} from 'rxjs/operators'; +import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -814,33 +814,6 @@ describe('Observable.lift', () => { ); }); - it('should compose through publishBehavior and refCount', (done) => { - const result = new MyCustomObservable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); - }).pipe( - publishBehavior(0), - refCount(), - map((x) => 10 * x) - ); - - expect(result instanceof MyCustomObservable).to.be.true; - - const expected = [0, 10, 20, 30]; - - result.subscribe( - { next: function (x) { - expect(x).to.equal(expected.shift()); - }, error: () => { - done(new Error('should not be called')); - }, complete: () => { - done(); - } } - ); - }); - it('should composes Subjects in the simple case', () => { const subject = new Subject(); @@ -951,26 +924,6 @@ describe('Observable.lift', () => { expect(emitted).to.deep.equal([100, 200, 300]); }); - it('should compose through publishBehavior and refCount, even if it is a Subject', () => { - const subject = new Subject(); - - const result = subject.pipe( - publishBehavior(0), - refCount(), - map((x) => 10 * x) - ) as any as Subject; // Yes, this is correct. - - expect(result instanceof Subject).to.be.true; - - const emitted: any[] = []; - result.subscribe(value => emitted.push(value)); - - result.next(10); - result.next(20); - result.next(30); - - expect(emitted).to.deep.equal([0, 100, 200, 300]); - }); }); it('should compose through multicast with selector function', (done) => { diff --git a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts index 3f5b1b1114..4b23cad1d9 100644 --- a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts +++ b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts @@ -1,6 +1,6 @@ /** @prettier */ import { Observable, ConnectableObservable, connectable, of, AsyncSubject, BehaviorSubject, ReplaySubject, Subject, merge } from 'rxjs'; -import { connect, share, multicast, publish, publishBehavior, refCount, repeat, retry } from 'rxjs/operators'; +import { connect, share, multicast, publish, refCount, repeat, retry } from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -33,15 +33,6 @@ describe('multicasting equivalent tests', () => { (source) => source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) ); - testEquivalents( - 'publishBehavior("X"), refCount() and share({ connector: () => new BehaviorSubject("X"), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', - (source) => source.pipe(publishBehavior('X'), refCount()), - (source) => - source.pipe( - share({ connector: () => new BehaviorSubject('X'), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }) - ) - ); - const fn = (source: Observable) => merge(source, source); testEquivalents( diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 4070478b87..267f5093a6 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -131,7 +131,6 @@ describe('index', () => { expect(index.pairwise).to.exist; expect(index.pluck).to.exist; expect(index.publish).to.exist; - expect(index.publishBehavior).to.exist; expect(index.raceWith).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index 7344f475cf..c15e591554 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -55,7 +55,6 @@ describe('operators/index', () => { expect(index.partition).to.exist; expect(index.pluck).to.exist; expect(index.publish).to.exist; - expect(index.publishBehavior).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; expect(index.repeatWhen).to.exist; diff --git a/spec/operators/publishBehavior-spec.ts b/spec/operators/publishBehavior-spec.ts deleted file mode 100644 index 3230de2b14..0000000000 --- a/spec/operators/publishBehavior-spec.ts +++ /dev/null @@ -1,404 +0,0 @@ -import { expect } from 'chai'; -import { publishBehavior, mergeMapTo, tap, mergeMap, refCount, retry, repeat } from 'rxjs/operators'; -import { ConnectableObservable, of, Subscription, Observable, pipe } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {publishBehavior} */ -describe('publishBehavior operator', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should mirror a simple source Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs = ' ^--------------!'; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const expected = ' 0-1-2---3-4--5-|'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should return a ConnectableObservable-ish', () => { - const source = of(1).pipe(publishBehavior(1)) as ConnectableObservable; - expect(typeof (source)._subscribe === 'function').to.be.true; - expect(typeof (source).getSubject === 'function').to.be.true; - expect(typeof source.connect === 'function').to.be.true; - expect(typeof source.refCount === 'function').to.be.true; - }); - - it('should only emit default value if connect is not called, despite subscriptions', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs: string[] = []; - const published = source.pipe(publishBehavior('0')); - const expected = ' 0 '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should multicast the same values to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-| '); - const sourceSubs = ' ^-----------! '; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast an error from the source to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast the same values to multiple observers, but is unsubscribed explicitly and early', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const unsub = ' ---------u '; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3- '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - it('should not break unsubscription chains when result is unsubscribed explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe( - mergeMap((x) => of(x)), - publishBehavior('0') - ) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3- '; - const unsub = ' ---------u '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - describe('with refCount()', () => { - it('should connect when first subscriber subscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^-----------!'; - const replayed = source.pipe(publishBehavior('0'), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const expected1 = ' ---01-2-3----4-|'; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const expected2 = ' -------23----4-|'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(replayed)); - const expected3 = ' -----------3-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should disconnect when last subscriber unsubscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^--------! '; - const replayed = source.pipe(publishBehavior('0'), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const unsub1 = ' ----------! '; - const expected1 = ' ---01-2-3-- '; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const unsub2 = ' ------------! '; - const expected2 = ' -------23---- '; - - expectObservable(subscriber1, unsub1).toBe(expected1); - expectObservable(subscriber2, unsub2).toBe(expected2); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be retryable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishBehavior('0'), refCount(), retry(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be repeatable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publishBehavior('0'), refCount(), repeat(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' 01-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' ----23----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' --------3-4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - }); - - it('should emit completed when subscribed after completed', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishBehavior(0)) as ConnectableObservable; - - connectable.subscribe(function (x) { - results1.push(x); - }); - - expect(results1).to.deep.equal([0]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([0, 1, 2, 3, 4]); - expect(results2).to.deep.equal([]); - expect(subscriptions).to.equal(1); - - connectable.subscribe({ - next: function (x) { - results2.push(x); - }, - error: (x) => { - done(new Error('should not be called')); - }, - complete: () => { - expect(results2).to.deep.equal([]); - done(); - }, - }); - }); - - it('should multicast an empty source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('| '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const expected = ' (0|)'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a never source', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold('-'); - const sourceSubs = ' ^'; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const expected = ' 0'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a throw source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('# '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publishBehavior('0')) as ConnectableObservable; - const expected = ' (0#)'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast one observable to multiple observers', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - }); - - const connectable = source.pipe(publishBehavior(0)) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - expect(results1).to.deep.equal([0]); - - connectable.connect(); - - expect(results2).to.deep.equal([]); - - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([0, 1, 2, 3, 4]); - expect(results2).to.deep.equal([4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should follow the RxJS 4 behavior and emit nothing to observer after completed', (done) => { - const results: number[] = []; - - const source = new Observable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publishBehavior(0)) as ConnectableObservable; - - connectable.connect(); - - connectable.subscribe((x) => { - results.push(x); - }); - - expect(results).to.deep.equal([]); - done(); - }); - - it('should be referentially-transparent', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source1 = cold('-1-2-3-4-5-|'); - const source1Subs = ' ^----------!'; - const expected1 = ' x1-2-3-4-5-|'; - const source2 = cold('-6-7-8-9-0-|'); - const source2Subs = ' ^----------!'; - const expected2 = ' x6-7-8-9-0-|'; - - // Calls to the _operator_ must be referentially-transparent. - const partialPipeLine = pipe(publishBehavior('x')); - - // The non-referentially-transparent publishing occurs within the _operator function_ - // returned by the _operator_ and that happens when the complete pipeline is composed. - const published1 = source1.pipe(partialPipeLine) as ConnectableObservable; - const published2 = source2.pipe(partialPipeLine) as ConnectableObservable; - - expectObservable(published1).toBe(expected1); - expectSubscriptions(source1.subscriptions).toBe(source1Subs); - expectObservable(published2).toBe(expected2); - expectSubscriptions(source2.subscriptions).toBe(source2Subs); - - published1.connect(); - published2.connect(); - }); - }); -}); diff --git a/src/index.ts b/src/index.ts index b073cd51a5..99776a8dbf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -151,7 +151,6 @@ export { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWit export { pairwise } from './internal/operators/pairwise'; export { pluck } from './internal/operators/pluck'; export { publish } from './internal/operators/publish'; -export { publishBehavior } from './internal/operators/publishBehavior'; export { raceWith } from './internal/operators/raceWith'; export { reduce } from './internal/operators/reduce'; export { repeat, RepeatConfig } from './internal/operators/repeat'; diff --git a/src/internal/operators/publishBehavior.ts b/src/internal/operators/publishBehavior.ts deleted file mode 100644 index d94589c09c..0000000000 --- a/src/internal/operators/publishBehavior.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Observable } from '../Observable'; -import { BehaviorSubject } from '../BehaviorSubject'; -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { UnaryFunction } from '../types'; - -/** - * Creates a {@link ConnectableObservable} that utilizes a {@link BehaviorSubject}. - * - * @param initialValue The initial value passed to the {@link BehaviorSubject}. - * @return A function that returns a {@link ConnectableObservable} - * @deprecated Will be removed in v8. To create a connectable observable that uses a - * {@link BehaviorSubject} under the hood, use {@link connectable}. - * `source.pipe(publishBehavior(initValue))` is equivalent to - * `connectable(source, { connector: () => new BehaviorSubject(initValue), resetOnDisconnect: false })`. - * If you're using {@link refCount} after `publishBehavior`, use the {@link share} operator instead. - * `source.pipe(publishBehavior(initValue), refCount())` is equivalent to - * `source.pipe(share({ connector: () => new BehaviorSubject(initValue), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }))`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publishBehavior(initialValue: T): UnaryFunction, ConnectableObservable> { - // Note that this has *never* supported the selector function. - return (source) => { - const subject = new BehaviorSubject(initialValue); - return new ConnectableObservable(source, () => subject); - }; -} diff --git a/src/operators/index.ts b/src/operators/index.ts index 13d1d67537..e341603726 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -56,7 +56,6 @@ export { pairwise } from '../internal/operators/pairwise'; export { partition } from '../internal/operators/partition'; export { pluck } from '../internal/operators/pluck'; export { publish } from '../internal/operators/publish'; -export { publishBehavior } from '../internal/operators/publishBehavior'; export { race } from '../internal/operators/race'; export { raceWith } from '../internal/operators/raceWith'; export { reduce } from '../internal/operators/reduce'; From 312a5bb53724002f92c7bab35e29f17121fff78f Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:32:56 +0200 Subject: [PATCH 06/15] feat(operator): removed deprecated `publish` operator BREAKING CHANGE: The `publish` operator is no longer available. Use `share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or ` connectable(source$, { connector: () => new Subject(), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publish). --- docs_app/content/guide/operators.md | 1 - .../assets/images/marble-diagrams/publish.png | Bin 44370 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 2 +- spec-dtslint/operators/publish-spec.ts | 23 - spec/Observable-spec.ts | 52 +-- .../multicasting-deprecations-spec.ts | 16 +- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/publish-spec.ts | 411 ------------------ spec/operators/refCount-spec.ts | 74 ---- src/index.ts | 1 - src/internal/observable/dom/webSocket.ts | 2 +- src/internal/operators/publish.ts | 93 ---- src/internal/operators/shareReplay.ts | 2 +- src/operators/index.ts | 1 - 16 files changed, 5 insertions(+), 676 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/publish.png delete mode 100644 spec-dtslint/operators/publish-spec.ts delete mode 100644 spec/operators/publish-spec.ts delete mode 100644 spec/operators/refCount-spec.ts delete mode 100644 src/internal/operators/publish.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index fa26226e85..1449af189e 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -216,7 +216,6 @@ Also see the [Join Creation Operators](#join-creation-operators) section above. ### Multicasting Operators - [`multicast`](/api/operators/multicast) -- [`publish`](/api/operators/publish) - [`share`](/api/operators/share) ### Error Handling Operators diff --git a/docs_app/src/assets/images/marble-diagrams/publish.png b/docs_app/src/assets/images/marble-diagrams/publish.png deleted file mode 100644 index 0834f221bbccfe7859e31f60df3e3f458ce6e951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44370 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 diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index 8d1ca885c4..6cd0e4df1e 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -66,7 +66,6 @@ export type ApiUnion = | 'partition' | 'pipe' | 'pluck' - | 'publish' | 'race' | 'range' | 'reduce' diff --git a/docs_app/tools/decision-tree-generator/src/tree.yml b/docs_app/tools/decision-tree-generator/src/tree.yml index fa5e47ca4e..fccbee77cd 100644 --- a/docs_app/tools/decision-tree-generator/src/tree.yml +++ b/docs_app/tools/decision-tree-generator/src/tree.yml @@ -255,7 +255,7 @@ - label: share - label: and start it manually or imperatively children: - - label: publish + - label: connectable - label: using a specific subject implementation children: - label: multicast diff --git a/spec-dtslint/operators/publish-spec.ts b/spec-dtslint/operators/publish-spec.ts deleted file mode 100644 index 64fc468a3d..0000000000 --- a/spec-dtslint/operators/publish-spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { of, Observable } from 'rxjs'; -import { publish } from 'rxjs/operators'; - -it('should support empty parameter', () => { - const a = of(1, 2, 3).pipe(publish()); // $ExpectType Observable -}); - -it('should infer when type is specified', () => { - const a = of(1, 2, 3).pipe(publish()); // $ExpectType Observable -}); - -it('should infer correctly with parameter', () => { - const a = of(1, 2, 3).pipe(publish(x => x)); // $ExpectType Observable - const b = of('a', 'b', 'c').pipe(publish(x => x)); // $ExpectType Observable -}); - -it('should enforce type on selector', () => { - const a = of(1, 2, 3).pipe(publish((x: Observable) => x)); // $ExpectError -}); - -it('should support union types in selector', () => { - const a = of(1, 2, 3).pipe(publish(() => Math.random() > 0.5 ? of(123) : of('test'))); // $ExpectType Observable -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index e109363b67..b35b2d2a97 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, publish, share} from 'rxjs/operators'; +import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -786,34 +786,6 @@ describe('Observable.lift', () => { ); }); - - it('should compose through publish and refCount', (done) => { - const result = new MyCustomObservable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); - }).pipe( - publish(), - refCount(), - map((x) => 10 * x) - ); - - expect(result instanceof MyCustomObservable).to.be.true; - - const expected = [10, 20, 30]; - - result.subscribe( - { next: function (x) { - expect(x).to.equal(expected.shift()); - }, error: () => { - done(new Error('should not be called')); - }, complete: () => { - done(); - } } - ); - }); - it('should composes Subjects in the simple case', () => { const subject = new Subject(); @@ -902,28 +874,6 @@ describe('Observable.lift', () => { expect(emitted).to.deep.equal([100, 200, 300]); }); - - it('should compose through publish and refCount, even if it is a Subject', () => { - const subject = new Subject(); - - const result = subject.pipe( - publish(), - refCount(), - map((x) => 10 * x) - ) as any as Subject; // Yes, this is correct. - - expect(result instanceof Subject).to.be.true; - - const emitted: any[] = []; - result.subscribe(value => emitted.push(value)); - - result.next(10); - result.next(20); - result.next(30); - - expect(emitted).to.deep.equal([100, 200, 300]); - }); - }); it('should compose through multicast with selector function', (done) => { diff --git a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts index 4b23cad1d9..e776ea9e10 100644 --- a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts +++ b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts @@ -1,6 +1,6 @@ /** @prettier */ import { Observable, ConnectableObservable, connectable, of, AsyncSubject, BehaviorSubject, ReplaySubject, Subject, merge } from 'rxjs'; -import { connect, share, multicast, publish, refCount, repeat, retry } from 'rxjs/operators'; +import { connect, share, multicast, refCount, repeat, retry } from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -27,20 +27,6 @@ describe('multicasting equivalent tests', () => { (source) => source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) ); - testEquivalents( - 'publish(), refCount() and share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', - (source) => source.pipe(publish(), refCount()), - (source) => source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) - ); - - const fn = (source: Observable) => merge(source, source); - - testEquivalents( - 'publish(fn) and connect({ setup: fn })', - (source) => source.pipe(publish(fn)), - (source) => source.pipe(connect(fn)) - ); - /** * Used to test a variety of scenarios with multicast operators that should be equivalent. * @param name The name to add to the test output diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 267f5093a6..2349cb9072 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -130,7 +130,6 @@ describe('index', () => { expect(index.observeOn).to.exist; expect(index.pairwise).to.exist; expect(index.pluck).to.exist; - expect(index.publish).to.exist; expect(index.raceWith).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index c15e591554..4bd493b58f 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -54,7 +54,6 @@ describe('operators/index', () => { expect(index.pairwise).to.exist; expect(index.partition).to.exist; expect(index.pluck).to.exist; - expect(index.publish).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; expect(index.repeatWhen).to.exist; diff --git a/spec/operators/publish-spec.ts b/spec/operators/publish-spec.ts deleted file mode 100644 index 9e9f8dd52b..0000000000 --- a/spec/operators/publish-spec.ts +++ /dev/null @@ -1,411 +0,0 @@ -import { expect } from 'chai'; -import { publish, zipWith, mergeMapTo, mergeMap, map, tap, refCount, retry, repeat } from 'rxjs/operators'; -import { ConnectableObservable, of, Subscription, Observable, pipe } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {publish} */ -describe('publish operator', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should mirror a simple source Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs = ' ^--------------!'; - const published = source.pipe(publish()) as ConnectableObservable; - const expected = ' --1-2---3-4--5-|'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should return a ConnectableObservable-ish', () => { - const source = of(1).pipe(publish()) as ConnectableObservable; - expect(typeof (source)._subscribe === 'function').to.be.true; - expect(typeof (source).getSubject === 'function').to.be.true; - expect(typeof source.connect === 'function').to.be.true; - expect(typeof source.refCount === 'function').to.be.true; - }); - - it('should do nothing if connect is not called, despite subscriptions', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('--1-2---3-4--5-|'); - const sourceSubs: string[] = []; - const published = source.pipe(publish()); - const expected = ' - '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should multicast the same values to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publish()) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ----------4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should accept selectors', () => { - testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const source = hot(' -1-2-3----4-|'); - const sourceSubs = [ - ' ^-----------!', - ' ----^-------!', - ' --------^---!', - ]; - const published = source.pipe( - publish((x) => - x.pipe( - zipWith(x), - map(([a, b]) => (parseInt(a) + parseInt(b)).toString()) - ) - ) - ); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -2-4-6----8-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----6----8-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ----------8-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should multicast an error from the source to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publish()) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ----------4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast the same values to multiple observers, but is unsubscribed explicitly and early', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe(publish()) as ConnectableObservable; - const unsub = ' ---------u '; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ---------- '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - it('should not break unsubscription chains when result is unsubscribed explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^--------! '; - const published = source.pipe( - mergeMap((x) => of(x)), - publish() - ) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ---------- '; - const unsub = ' ---------u '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = published.connect(); - }); - }); - - describe('with refCount()', () => { - it('should connect when first subscriber subscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^-----------!'; - const replayed = source.pipe(publish(), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const expected1 = ' ----1-2-3----4-|'; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const expected2 = ' --------3----4-|'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(replayed)); - const expected3 = ' -------------4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should disconnect when last subscriber unsubscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ---^--------! '; - const replayed = source.pipe(publish(), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(replayed)); - const unsub1 = ' ----------! '; - const expected1 = ' ----1-2-3-- '; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(replayed)); - const unsub2 = ' ------------! '; - const expected2 = ' --------3---- '; - - expectObservable(subscriber1, unsub1).toBe(expected1); - expectObservable(subscriber2, unsub2).toBe(expected2); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be retryable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-#'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publish(), refCount(), retry(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ----------4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - - it('should NOT be repeatable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const source = cold(' -1-2-3----4-|'); - const sourceSubs = ' ^-----------!'; - const published = source.pipe(publish(), refCount(), repeat(3)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(published)); - const expected1 = ' -1-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(published)); - const expected2 = ' -----3----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(published)); - const expected3 = ' ----------4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - }); - }); - }); - - it('should emit completed when subscribed after completed', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publish()) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([]); - expect(subscriptions).to.equal(1); - - connectable.subscribe({ - next: (x) => { - results2.push(x); - }, - error: (x) => { - done(new Error('should not be called')); - }, - complete: () => { - expect(results2).to.deep.equal([]); - done(); - }, - }); - }); - - it('should multicast an empty source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('| '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publish()) as ConnectableObservable; - const expected = ' | '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a never source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('-'); - const sourceSubs = ' ^'; - const published = source.pipe(publish()) as ConnectableObservable; - const expected = ' -'; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast a throw source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source = cold('# '); - const sourceSubs = ' (^!)'; - const published = source.pipe(publish()) as ConnectableObservable; - const expected = ' # '; - - expectObservable(published).toBe(expected); - expectSubscriptions(source.subscriptions).toBe(sourceSubs); - - published.connect(); - }); - }); - - it('should multicast one observable to multiple observers', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe(publish()) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([1, 2, 3, 4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should be referentially-transparent', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const source1 = cold('-1-2-3-4-5-|'); - const source1Subs = ' ^----------!'; - const expected1 = ' -1-2-3-4-5-|'; - const source2 = cold('-6-7-8-9-0-|'); - const source2Subs = ' ^----------!'; - const expected2 = ' -6-7-8-9-0-|'; - - // Calls to the _operator_ must be referentially-transparent. - const partialPipeLine = pipe(publish()); - - // The non-referentially-transparent publishing occurs within the _operator function_ - // returned by the _operator_ and that happens when the complete pipeline is composed. - const published1 = source1.pipe(partialPipeLine) as ConnectableObservable; - const published2 = source2.pipe(partialPipeLine) as ConnectableObservable; - - expectObservable(published1).toBe(expected1); - expectSubscriptions(source1.subscriptions).toBe(source1Subs); - expectObservable(published2).toBe(expected2); - expectSubscriptions(source2.subscriptions).toBe(source2Subs); - - published1.connect(); - published2.connect(); - }); - }); -}); diff --git a/spec/operators/refCount-spec.ts b/spec/operators/refCount-spec.ts deleted file mode 100644 index 686043f2bb..0000000000 --- a/spec/operators/refCount-spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { expect } from 'chai'; -import { TestScheduler } from 'rxjs/testing'; -import { refCount, publish } from 'rxjs/operators'; -import { NEVER, noop, Observable } from 'rxjs'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {refCount} */ -describe('refCount', () => { - it('should turn a multicasted Observable an automatically (dis)connecting hot one', () => { - const testScheduler = new TestScheduler(observableMatcher); - - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' --1-2---3-4--5-|'); - const e1Subs = ' ^--------------!'; - const expected = '--1-2---3-4--5-|'; - - const result = e1.pipe(publish(), refCount()); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1Subs); - }); - }); - - it('should count references', () => { - const connectable = NEVER.pipe(publish()); - const refCounted = connectable.pipe(refCount()); - - const sub1 = refCounted.subscribe({ - next: noop, - }); - const sub2 = refCounted.subscribe({ - next: noop, - }); - const sub3 = refCounted.subscribe({ - next: noop, - }); - - expect((connectable as any)._refCount).to.equal(3); - - sub1.unsubscribe(); - sub2.unsubscribe(); - sub3.unsubscribe(); - }); - - it('should unsub from the source when all other subscriptions are unsubbed', (done) => { - let unsubscribeCalled = false; - const connectable = new Observable((observer) => { - observer.next(true); - return () => { - unsubscribeCalled = true; - }; - }).pipe(publish()); - - const refCounted = connectable.pipe(refCount()); - - const sub1 = refCounted.subscribe(() => { - //noop - }); - const sub2 = refCounted.subscribe(() => { - //noop - }); - const sub3 = refCounted.subscribe(() => { - expect((connectable as any)._refCount).to.equal(1); - }); - - sub1.unsubscribe(); - sub2.unsubscribe(); - sub3.unsubscribe(); - - expect((connectable as any)._refCount).to.equal(0); - expect(unsubscribeCalled).to.be.true; - done(); - }); -}); diff --git a/src/index.ts b/src/index.ts index 99776a8dbf..17010f2d01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -150,7 +150,6 @@ export { observeOn } from './internal/operators/observeOn'; export { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWith'; export { pairwise } from './internal/operators/pairwise'; export { pluck } from './internal/operators/pluck'; -export { publish } from './internal/operators/publish'; export { raceWith } from './internal/operators/raceWith'; export { reduce } from './internal/operators/reduce'; export { repeat, RepeatConfig } from './internal/operators/repeat'; diff --git a/src/internal/observable/dom/webSocket.ts b/src/internal/observable/dom/webSocket.ts index d642f0b4b3..7278bab36c 100644 --- a/src/internal/observable/dom/webSocket.ts +++ b/src/internal/observable/dom/webSocket.ts @@ -70,7 +70,7 @@ import { WebSocketSubject, WebSocketSubjectConfig } from './WebSocketSubject'; * as messages pushed via `next`. Also bear in mind that these messages will be sent on *every* subscription and * unsubscription. This is potentially dangerous, because one consumer of an Observable may unsubscribe and the server * might stop sending messages, since it got unsubscription message. This needs to be handled - * on the server or using {@link publish} on a Observable returned from 'multiplex'. + * on the server or using {@link connectable} on a Observable returned from 'multiplex'. * * Last argument to `multiplex` is a `messageFilter` function which should return a boolean. It is used to filter out messages * sent by the server to only those that belong to simulated WebSocket stream. For example, server might mark these diff --git a/src/internal/operators/publish.ts b/src/internal/operators/publish.ts deleted file mode 100644 index 105cd36729..0000000000 --- a/src/internal/operators/publish.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Observable } from '../Observable'; -import { Subject } from '../Subject'; -import { multicast } from './multicast'; -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { MonoTypeOperatorFunction, OperatorFunction, UnaryFunction, ObservableInput, ObservedValueOf } from '../types'; -import { connect } from './connect'; - -/** - * Returns a connectable observable that, when connected, will multicast - * all values through a single underlying {@link Subject} instance. - * - * @deprecated Will be removed in v8. To create a connectable observable, use {@link connectable}. - * `source.pipe(publish())` is equivalent to - * `connectable(source, { connector: () => new Subject(), resetOnDisconnect: false })`. - * If you're using {@link refCount} after `publish`, use {@link share} operator instead. - * `source.pipe(publish(), refCount())` is equivalent to - * `source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }))`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publish(): UnaryFunction, ConnectableObservable>; - -/** - * Returns an observable, that when subscribed to, creates an underlying {@link Subject}, - * provides an observable view of it to a `selector` function, takes the observable result of - * that selector function and subscribes to it, sending its values to the consumer, _then_ connects - * the subject to the original source. - * - * @param selector A function used to setup multicasting prior to automatic connection. - * - * @deprecated Will be removed in v8. Use the {@link connect} operator instead. - * `publish(selector)` is equivalent to `connect(selector)`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publish>(selector: (shared: Observable) => O): OperatorFunction>; - -/** - * Returns a ConnectableObservable, which is a variety of Observable that waits until its connect method is called - * before it begins emitting items to those Observers that have subscribed to it. - * - * Makes a cold Observable hot - * - * ![](publish.png) - * - * ## Examples - * - * Make `source$` hot by applying `publish` operator, then merge each inner observable into a single one - * and subscribe - * - * ```ts - * import { zip, interval, of, map, publish, merge, tap } from 'rxjs'; - * - * const source$ = zip(interval(2000), of(1, 2, 3, 4, 5, 6, 7, 8, 9)) - * .pipe(map(([, number]) => number)); - * - * source$ - * .pipe( - * publish(multicasted$ => - * merge( - * multicasted$.pipe(tap(x => console.log('Stream 1:', x))), - * multicasted$.pipe(tap(x => console.log('Stream 2:', x))), - * multicasted$.pipe(tap(x => console.log('Stream 3:', x))) - * ) - * ) - * ) - * .subscribe(); - * - * // Results every two seconds - * // Stream 1: 1 - * // Stream 2: 1 - * // Stream 3: 1 - * // ... - * // Stream 1: 9 - * // Stream 2: 9 - * // Stream 3: 9 - * ``` - * - * @see {@link publishLast} - * @see {@link publishReplay} - * @see {@link publishBehavior} - * - * @param {Function} [selector] - Optional selector function which can use the multicasted source sequence as many times - * as needed, without causing multiple subscriptions to the source sequence. - * Subscribers to the given source will receive all notifications of the source from the time of the subscription on. - * @return A function that returns a ConnectableObservable that upon connection - * causes the source Observable to emit items to its Observers. - * @deprecated Will be removed in v8. Use the {@link connectable} observable, the {@link connect} operator or the - * {@link share} operator instead. See the overloads below for equivalent replacement examples of this operator's - * behaviors. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function publish(selector?: OperatorFunction): MonoTypeOperatorFunction | OperatorFunction { - return selector ? (source) => connect(selector)(source) : (source) => multicast(new Subject())(source); -} diff --git a/src/internal/operators/shareReplay.ts b/src/internal/operators/shareReplay.ts index 96d6e0c4dc..406eaaf03e 100644 --- a/src/internal/operators/shareReplay.ts +++ b/src/internal/operators/shareReplay.ts @@ -139,7 +139,7 @@ export function shareReplay(bufferSize?: number, windowTime?: number, schedul * // ... * ``` * - * @see {@link publish} + * @see {@link connectable} * @see {@link share} * * @param configOrBufferSize Maximum element count of the replay buffer or {@link ShareReplayConfig configuration} diff --git a/src/operators/index.ts b/src/operators/index.ts index e341603726..60932a1f45 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -55,7 +55,6 @@ export { onErrorResumeNextWith } from '../internal/operators/onErrorResumeNextWi export { pairwise } from '../internal/operators/pairwise'; export { partition } from '../internal/operators/partition'; export { pluck } from '../internal/operators/pluck'; -export { publish } from '../internal/operators/publish'; export { race } from '../internal/operators/race'; export { raceWith } from '../internal/operators/raceWith'; export { reduce } from '../internal/operators/reduce'; From 6226ad6f92f1dd1a296fe4242298ddec7e7060d0 Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:41:22 +0200 Subject: [PATCH 07/15] feat(operator): removed deprecated `multicast` operator BREAKING CHANGE: The `multicast` operator is no longer available. Use `share({ connector: () => new Subject() })` or `connectable(source$, {connector: () => new Subject() })` [Multicasting](https://rxjs.dev/deprecations/multicasting#multicast). --- docs_app/content/guide/operators.md | 1 - .../images/marble-diagrams/multicast.png | Bin 54006 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 2 +- spec-dtslint/operators/multicast-spec.ts | 42 - spec/Observable-spec.ts | 92 +- .../multicasting-deprecations-spec.ts | 95 -- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/multicast-spec.ts | 821 ------------------ spec/operators/repeat-spec.ts | 8 +- spec/operators/retry-spec.ts | 9 +- src/index.ts | 1 - src/internal/operators/multicast.ts | 98 --- src/operators/index.ts | 1 - 15 files changed, 6 insertions(+), 1167 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/multicast.png delete mode 100644 spec-dtslint/operators/multicast-spec.ts delete mode 100644 spec/deprecation-equivalents/multicasting-deprecations-spec.ts delete mode 100644 spec/operators/multicast-spec.ts delete mode 100644 src/internal/operators/multicast.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index 1449af189e..cd53cbde03 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -215,7 +215,6 @@ Also see the [Join Creation Operators](#join-creation-operators) section above. ### Multicasting Operators -- [`multicast`](/api/operators/multicast) - [`share`](/api/operators/share) ### Error Handling Operators diff --git a/docs_app/src/assets/images/marble-diagrams/multicast.png b/docs_app/src/assets/images/marble-diagrams/multicast.png deleted file mode 100644 index 9b8fce695f550ca508b201c36b2988ad1e4f56b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54006 zcmeFYXIN9)wgwzjL`8Hf(nLUID@qXo=}n|5y(V-Nq?b?(NJkNoF1>d`3lM?OORxY+ zuc0@Qme7QRk`VY-*!!Gw@AsYO-uv(Sb9jB8te9l2ImaAxj4{V}N2r#DGTnvi7eF8o z-Lt0(Iv@}=aCz#+AE$s95BSqa;N^^soVpwcR1r;k_=583P0Ob`>L8H!T@Wbn9SB4O z{wr_=1cE&Tfw0d(Ac~k#|Hm~5Q~f zb>=@0{D(CDBhvpU&EL8}*%pCg;ZXjT=6#V$mzVS3zt9-5+j?a$;@%@!Tb#egP{oGr zUkvNZ+jk7>yRQrg4r>r7!3bKhT(zVE)m#Ccc3x>)WhyjJm+@X(smSZNi%vgu+wPj{ z`kWNRU+DTV@#KEb7r!TPLZX^{=eL8qm@H=7TO#38XS$ms{a8t0U$bvE%Dz!I2*ua3 zTz`8pW%&(UcA29B4Oa|TfMC3!{*J+pQ-OuIKxa*6x{8vt`SU!~XN0{*e;HZYM-~g; zRlmAwjt(Fn5j0_9BlCJRGfaPr;>&y$e;Z~CU0820fa=WQ82Ay( zJOYk-)7jL)NKA(A9ITh=_x(G|K0SM>n}m{i#CzmxZq})Hwtcxy9m_-7o*GYor1L9{ z(BUBa*s!F$%L&XixSypWmF^Sfw~@vF`JZq5e9s;u@J%mV zZ8U7gT3pwfC+>lW^CSZ~bjA3!C>5yJq@y4$^FX^sus#veX^w{F^p+(6zu@rG_5ZSR zRs3vH7Ax4Tb?Y;5XI>%4zPFNX#&k`O5cPd^pE&a_Gwf@|dAuN3&R$x(rV}f{`1FGW zrq*XM)sSB=ZE%twsx_n-r^1jvEz|Yo`)!?NHlAF+63^o1?WVqum-v(X%~0xHjzUc7!7NS7N$J@?F=nkw=_KEsZqMQ=~V&T9*2t#0}-ae1Oa zYsI<1`E2xg=G8)k#?3!Q?(oc3eNRKTtbaleUg$^+-Q|z=a5TDY>$=mSc-k$x z$|j5TcxHdE9X;FUCA&;cZ(4Bi&n*k{aL}ZM9@SYFOf5utm<&kUR#*m^k&*)Z8lmQJ zhJ{0K{rlVPM@I^H*`@_h;J0E++9v2sJ|rRA$lZ5$-Q97@;aD*HsOT(DgOAk%^JeS2 zlnEzFnJWKikyvYQ@ACh_#)_Xn-)O=G>TExYbRY-q+{puGXXZ{#85X^}?K9yZuBFRu zCb#`~{|GqK>Y{O`HIP1(g%yDW;96T&`9~jN)Z8Ocenw|2a`8%~u~_kj6=^L^cc<#eDqyjDeWSXTA~P zs0E)axnP;AvR1oX{h{S4UKK?J3be!-WSyQDYF9`wZ?=_t8I*s)uP4z8*R59X;Lu_L zORW)q!baOyY#BuIjOc{fY2ERA{A23mmgqF^ZP(T^Yd9B#k6Dq8wpDof!YN%Q<~vKB z=}u=gyLrOIm52s6o&R32!mZMuRbhSH7(2s4tBk~&uF~S>x6Qtc==B*Vw=UYy z0)vJ&Djz`jWUC?Q5Sef%w8Q{^s7#m=73hN|n{kmPu9?gZwr&3PBpzKA++y7&xKO}1 zE+eg+q!aywTx>b-4=bImESVpFau%iKmayMD{=~d$@jJ55_o`T_#?Y;iW?G$&Q!X3z zZz)3y6BmG_e5T)twAhG|Vf@5F^)Q{D>fy(48`RUZ4NUQVR=Ww~kW>c!BTe_+&Y$kW zmT9h^?M&b=9~p08AxPCZ*rejG=de!_29e_Q?su0i@|}71FjbOr8DSezGl?ztuaco{ z+ThMXj&IwymlXyL?aLB=_x`lpRZ--)L*y|!2WmZ%5E()oF8elhy-YK*!r4L212Sks zTsD!y31JQDl-VXXcE3Qw9NiN7M;*t}1$xyAEmHn1(Lzd;i4@eo^)@|)Y$RUHOb)r` z9*eICboxsHAIH{DAA1~6lAV$w7Wnn{D{Z@y3twb`Nnb{2mAe+D(U*jIgfBN_Nh*Td z)~Z9;&P!hP__IJ$Eh||D#rWr-OZmxV?s`gfcQ)zHl8yex!TPjraXmsAoe111#2iAh zI1GkbUn6sjLPJ}^F{c3ESA*uifPoIIrLi!eO&Hzxt53e29beVBHXR3-i$UF4((U+C zjWyWRKC&-x2&z(a=Dy$PjVGCRMfWyyCsZ!AQ^_tP09C!Yx^%&<@O#OJg9o0epXuFW zE&O9;7$3@mE-ov8F8=w3M74K%gXS>0ih2{1c4faeLq!R<*yuJbTQX4dK zL`IV&wZ8MnLvt;2Od56L&ur-mAB(*YyVk_+%oZmN2Iie|lVPa7PlGPrp?M1C30`jX ztRdYSh#qhO1xjFye%G9a_F&gEa*%||FUjzpJpV38t_DJ+u*h=$5azg5%cl9OLCS48 zW&KU~G&ix@sHU&_VZ#R%VEC@UCK_U3=3J_q@?qEP)(3n9=C2*}MuFhA*EP-W$@D|# zPt_P+Yxtl5vS9Ws+pEpk-{?f-mj*CGu29@2!g+@c-zdz$)bMX6X8^ z`35~33H$VAHTMP^+2}#ESJ`W(SN&_rAN>n1&Avjo7hhjW z2mMYWpig)H3OH_7q<@gU;*;z5nzXe$Z>^|2nb4Diar#)nxGxtv6^j&JDzu}NpCuZh@;`FFweww51Q2mHH@M&taALObCfe0mbe+_f$G zH@^|@ANhd6oAV)hxBEI;1Y=*&Q`Mo!|+XF@2^QL{>->aM14XHyr0#xpW1&zSxx! zLqNO|YDRoMq}vhgE`(DB`ixdALimmTFwDvx-4%R3v9iYFqup`a6+5=2otC+O1&HYv zJ#{r@F4Y0MX720qg;eJY4PS3$tizL+^P_`pZiAv^yBq?XI4{-!UghJ>Oj+NftpoWg z4ea-nyPI#7w5|gI#USEU##_jdRVpXsb@`SFN_0#U#e%DOln?2Mp+^3(F@ctHvpz`6 zzGB^+zH-_Q3YznWIX-T^3{67cnyL<1oi06UjN&Y|jB$ZE+J1EoaaX1Xesj^drXp?A z95~dh0orL=ILENGxMm(Eu1Pd_ef`wjKK+~WbDl$Ekq^g2fR&XyjNdMdmxZG?VkP{H zc_C)KEQfQ8Ll-laAt4dKV46tpDW^+g)}IWU38+^x z$G<^IfLsbCL_B-@Vdeqq*`&|4L6{{DjDJp);+K(%uW1}z%vv7|_T-b`{ErT9*>D0o z=h&eISx@(8Elf^dK8Shp(77w& z4uU3u8S1C!a}g&{+VOCL-I0F%TLZb2SDa`S`dgvi)%ZxCAEM~}DE0LS1is8t#} zR@q}sTyJ=i%~}iZEBzFbXRg!nr2^(SG#%H#V4@b!TDzDnLJW&l1P)lqeGGb+xdk%o z>+1O04!QhzrD&*JzTCPP1)RBBKi6EF)_J9>jngRHEDhYHuGBi!ZgbG!G3ulLs>+%C zxtOMqJw2EDOR6oaHQzF9{d62+MWOz;;cmuA1MCeirUQ%*K|Kb!5CF{|pRh8nz56Y) zukx^}ZRoOEK~%6MZfp~mb%Cy1GoCfes?Cs%dofjxjkdqzXwpQE@{FaQKdY{}=in>0 z&YWot4SKjQ51fjlcJA(~ucduiq)p;CnQ6$Y_h=}CZaoe|@AEH@TwI^89V4FO_p13d z9&7VR-hkfeYeP>rLi|_dti{jCeST!dj2Z9iY{C^ra?T2?T?lBd0p^%8Gj!dFU+Dwu zu~kerTNPcs8e91OXa!wCv`Jck#BZm=q|;5mrtf?ywxlAC9cS{K1D=w6P`l6HW^xaZ z7!{SvPeAEus2qy%zllMr!ukOij_J@3p` zeQ`p@^TTkY1mka{Wr%`82 zPR~dM{dK-nEXyN&tiJrqgdYhcF#ZSG&E(|(cUgwhv8PiS!?peIMBDI|7|c0Pxj_db zRLbSJ^k!jQ@ODg_-EAlncR$v2R#aRivBbPsw|#Tx8o$=f^^u5}6d$XDrcdU--GGdq(J{BWYZw?Tfymhjzy)e1%2%4;Jg@nS{+F?UBq?%|fzBPxB+!?d2v9P5HZG zUmdROh$bFHbD+?U`DrB17hJ zhg4e|YXop2af)b*EcsOOrQ`xi>0GX~L2cahxQ#kDpPY$ zdE|h115}rsP3twkzGoOZOea3Ix1kLT_vFC;E`2s!@xhpFvZeb=tzxdp()mW6kkI-> zBlHEE$-a5%sDuk!z|Fg z>zbAET$}Jx$?)vO`VFh;weEq<`d=l6?0jpL>rzE^HH;IJ!~J7L&V$NzI;_w0`Bo`3=F_S0m>7%v zbopAkOm>csI#()d z!Trthho(z7aGCwmr&r2D8x=Fhd-rDxeY0W{SAQt5esX3_`6`&H*2uL>h&eq{a@R?V zXz%iCox5sVYL}?_-qB+ARP8}jub}*yhU2|whXKbbhn`(%K~hh?QE!^aqoCQlI8J`z zGo!npIu$nKZ;h5CIV`av_xLdNv&DADu##NpXeND!Fyry4#1zBvo#UTM0@EU40XEpB zjLI#R!p1AFg0q-7#6No2zUL6i%#R8t!yJh$DTjlJtOW9bF8ox6IC0(7-sZCfjnLh$ zO7ZneqZa~M4<)v}kAjCQ0tmX-Z%iG+)JO}I+RideZ$BS`loW}gG4eO4s9{2Zx4hO;ZJ}PI%XEW+m4#sLVfjrW2 zO%y#(YVpL zxwt0C*KH4LxwvG=;WeN+C`i?+j~#10w9G7(Nkqxny(v&fgzz(x;%*J%G+IDD&Z{O% z%XXJ*(MRa;fa7Dtn+(3Qy*^DIEtp%w6`#;iWnv{kp5@PaZ;+$D!^?i)E(xHzjvYREat#ohW=cT*=r0PS?|Dx+_;PIEuefIXl_!{enfn)(>Qgc& zJUY1XHps(tgY7Im==7yOme>H0`D>#>vBM8u#Q<7l<568?dPG{yqTby0vTS}e4SKzB zU_?F)G2T2LSX55pFxBY7zs#jGsEv$V=Gxfd*tjUSn%jTHTj0L4sJqPdrd;R#8^0mr z#?}Wy(-zD1m-b)8$4cYPo$qk}Q#~GxHgT%#=0`r=`8J$9efaGCr*x%EKeKi2YvuZw z%zL$K<%VT@uZT%o-9Jt}M_*_r-`&VN(TFZuA*O5Io843{t2ZLMmb$n42=;zK{MLLj zzyXr&O}ObD5WDxBi_r1nUpg_2U6!5lT57Zx<@w0J+#29~G+T_Hc#>iwN+d69J8Nf5 z2tYu4il8<2DgKLhfuJe-TgBB5l^dia*17`^s3|OXhv`K*D@a*cl;3otiExBOS07=B z#waz-yA!SGDU*BNJq>Ql8Mp3DGYU7mJTKYmRll=&%df>&f91G$o!pNIA?NwEbpKqJ zqT2GAm3K#!f0EhG&C0hr6^IzFV5s3E!MZvbpP*t%fGs|T$(>%)S7gYx{e((G+;~PpyG!5&l4=_*6#kT+4 zv7q>zrF?g9i>P=R#*Hx07`aZFSq;b%JY~xAa&G9dql1KMn~H*3Ok4bZf9%1KWL?SM z2=t>vg3>9rr!h_o9tYFXPedg9=;F$tYmR+T5io+ikI=`^N{+7XF?!xoC4F9OXDUK- z==w3H76eLfj#8JD_}a&kB@xhX+(5`zMk~;yvy)$rto$@PUDe~5G+Jo=h7oPhl9=1q z(0r5=?S8h^Dx}w>u8{`DyN0x+aT4xKEM0QUu`?jiA$|J_5J^W)sq}VV2ZIY)rWgB5 zoMd=-gUlf31KR}2scMl!?JYV=;hxvT?6jx=!9gxP#Vw_z@Bc%L!^Rb`A z-s)7L5Z_Q-sL1nakxaFr5=i-6I@Q*3T_t9@f2xG%z3>LUMJpqqy!>3Bj+kj}nxyA0 z-H&-kALDu28`a}T zt4!iV03kNg4R>!g@0@|l&nQXnK+}Ze-xOV({>F~!5qTBknGE}eGoo@i5_pp*m;@x@ zrJ&{6?t7gK=|2tYIfT;;Hqrv>_1%uI@-@kef=d{F&FUQXA_FjXH@4jS?C&&sAE$_T zrEWbs7Dg|pLr#bPOA@B_VCM90FPW=>l6EV`D@i6l&IQtY9|%@DgmcdW=dVqxmoE|A z^W_ZWFs>u8jG?u?$NF*aagTw-`ZYq_0ZBz!av z;$C&i*yv$*idD#}b(9%b9E`YIrz!fJrp%Z!rrw7`)rAmp)A8Q-!dQsAf8xRC_h*HX zL?7ecIm6?TnHoY!LMonL;8R==WyL30L47Fqo!%ZvQNTn#Kq^k>s=M>wrYtv(XnI_3 z(LeJXJxaK&hO`h1SOJ1ub3yRy$pW!2mKPc*Ows3@H53M+z z>g2|s+YGGmHn+(UDb>kjF%-?RfNJ9qJlUC$$O;UWpmzFPzEUA$l@=O|e;*dF79U!Lt0l?8PR55EPCQ1!b=G6o{tHI8y3q>=2MU z^~3ZyA#te)Cftzi>i}qYwjDv;?{+;kH}S2ZN4*2mn1(`cIF(D z(j}mQJq)eDk;i25!t*NlYX)(L_{bvfsco1m^+S^kArq=8^3i*X7IeN>%FFZMeJEp*{dIaD+g%6-8O#$%B{pmFrpkosM%E%fi#=p7`UwPTc0O2FKO=O7n$ z_E*%O>S!cn59>Oj2_Y#qAg*s z{ei3&AVF5P+wjY($9?@m%`Od=Jx^XZmPspjowTpA0SyTr%!hFJr=z1_2{xcf`qQ*5 zZ`~5Vv*8>CK8*_n7F!+&AS^THSz3FJlCPS5|4hFZ6t0-b&9Zvf2P&}I{uJ(%;ePRu$l~O9~pkykn;U{#6t-F%f#{-D-yDnwayLetc@i~_! z?Bn?id&sAr+ce%4`*-$p&{??DuppPXh6}NhK@;4zRnGmd-r*l7US@H(=;ZPwbH z{-Nwx-}tGyRI>`@FAR>}1YX1aw{XD;NF z%ulE!PutQm&#F|F?|<>O&VLKy;U)km?(*T+B8~MYOjkf$Q*Qrj09Ks7SJ*$8aa@n# z_DapOD>3~+b|?!|H5DZ?bcJZE?Di`jyCLXL?)-OzeiDLtET0b?;#KpxX{vv0H!Ew3 z!3LNZPP$pIn(hhuCRo~S1eDM7Xchg4`sC2d2qNjPtc$vGoH!q2v*h~hejgiu?{eur z5MvI~ePg-*bV%9(kRPX(f|X~3Wsm23#g%RP)G~-aM%`7F3;kl-p9(!WY;pZG-zdnM zZUdCX{yx++((Ik{;{#GLmp-k1sif_CU=Xmcx#8^5G$nOv?w#@OI(>gpEBaOAzmLV6 zCahHR^bWop)t9VRj0Ok-eu3qdZb-r2BtAzKn4so{nP2IY)PFgiuqFp|$BlHvirnU7 zkgixOP_#o@M|4khxy^2~As|(LWQ!`IXQr9K6t=!@wAE2)lEHQY<-Kpw#VQkCcpS#6 zA~~rWw!@ChK*G+QNP{N|JD1^b6-adP`AE$Q4nukVQU#!JE7s;Xwt&l^)$i4FaZc1_ zkvw$o+>d*tlzPQ9i2)f0UEP(2NuB|V>mYy3XV;{uU{cp*^K7bPO`DHV5&n&i_jmEf z)~x9(2j3dg*lfx{8{wcaSiSk*%CeG7L4em73DwU*76Fvy`!>v=)?QyI1P&aB`p{Fp zl8dDHP2Itht#iEXyYVT4YiJ|X&+pgc>XK)y@$Z}XN2D5)@-kDGfDpCGPF`r=iI~J{ z-=@%^(9!?b(dG6G8{$&W91!Qr_WjPtx}#s?u^S*{P1rVM-cl~+U0_F=Z#s@1flIe` zesazuRx~R)?#+gsJ<+aELl<3{0a(Tl0Z;x!5DH5}8;~O?cmI36U-<7jv zO)PqqJP>s9V!2>5BP?`4+n zJuc8?*fuX$lSVcmjT}x_-`ZY2cJtZI*-q#W1*W>BkzwgURNr6%(eUvPJiuAwq_2_x zbh-*Mfk*XRHQKih_2{KfJ#rUXJ~^QE<}#2mXb0l^@zf>9kGrE0M=3QgTMTTqE2hmz z+?cZFky?ko(1q&|wHy%=R}{aFpMj*yizMs@_bMEss}N#Mzf9G z$`^z2{searJrE|+IO^NR9S;T*RQkMJv`7wSD-1d6iqoy4vANvKe#1v<_w|~q5$BQX$;E(3>0~!K zSf^Ht|E;kyU(n9ksqUH{q8N~SY(L38TK6ngJ({~4Qk0zP2VH?>ogx2oA%jeVgNk7r)5Fu2^tObs^nlSj9O%wqOwR(?9w+WCHdNa|~@>{Zfnbl;gZd zvu=KARlh;wGY>{tQ0m{-(N_MaIvVER*U^CA{BLzMPP{r$fqr~y0;o9xb;F*9!X(K? zk&?m4!T#OtF@AMX>S+PV_mrBWm**Wmx?Osw_EJSQl9d%QTk>6FO%lJS5(YWgv&J0e zADws>v|-wjctYLr`(irT6=;`Ng*UzMG_e=66JWD{rAr4PjB7-77Dm$P_m z8}5G~9gw5{RdGaTq_cXRZy27r3h}Q!2I(TE-d>*uQGF*FOBKW}9dJ zZ)>*ay#ME#?N8z6^_}g5>FTS)6;BT(JYIL^4V}`tf=}h+nb~l;I|?wUK&}})D^mq- z_m^Iq+fWAB}5!UzOc??>FbViC_)>^k*~f zt~DY#HV5qQnCKNpfAHZ;;&bn@1wRECmw%w^-#+1MjtT|5+Xiovg)?Oi5uh<`UgYV! z_()k`lf>{!qSpE=<*nPa^vc?CUCuc#uXV*7S!ptC*n5O5QedUW(X&~mj8E}AiT{Rl0Q{tKG7omz&lsrF zxJ;SIQHTwKo?M9*GQgN_g5JARgxM83Mqj}-5mI{@%Ha%VRz%yIRZr<_KDc2cb$NB2 z)!M_?qeya?ja&VE)SZb0Lqytd-#PH?LxAa!XI>V{?K!fx|3O9_4@KPpZT*rE`Lqx% ziBa%!!yAjKPx73u1p?CUh=l~Dp!jACUkju&MHDv(hMV8l=H zflUDaC;GB^Y}RJ1_$8 z3%1IIu%w*<_$g^FA|3LRU6DE9Q$gotA%94i!wm7U`Rtac{iv1mZS_y04W2y>mZ=j2|}n(Vol>yMZiYR;QA^|XOq^0jG&PS!Q0;*}s&^{ZEC@-$PUCw@|9 z^vlX^ZeXi_%iuYu26-Nlyx_L!B_#j>2pa~Rf310J_xe#SX?6qJ=y*LK=Sz~Jak~^9 z2{pmAp(i-AgVU%P?QHuD*a`Na7`*@E~DAG#{ip)ZkdecW8MaKF|5Qd7gG}_v~0qE!cIBeNCmOREhaM!7J z^6X5`kr_R5bXG?C^?Ss-mj5#?68NrFySj0upLf&)ID0S=Al#9$252k&uT{YpZF7Ec z|IPru!ikpIc{cY+LOn!p@4-`GV)e@xF3jwu-dp-+Vg(#;MZ@Zq0h+G=-)vT)k&l)Z z?cX9&9@z}0KXV@(d!ZkU4Od+YsIPL!7VjRl;fm}iKCgzTSU=cUWMmRKmP>y{^7SYc z{8!xdQ6kN_;kN!c+-E|x6ddANc*&`*gGuFM! z^b%lyPo?{R?{59*+7i^q=aABL=m(IhHyJ(nwP3?X{MW5`t7@U>KqczIf`i9CyBp(; zHqbT17^DLEI%(d*?0;sQM@9Pd@lEzu9g}3KFEZKvVcD7 z!5kZs3{`E=I%3L=nlv-K`hJIXbkYEs8k}7F3Ug~Sc2fBrZ$skV>-EDj`C>~sHizi2 zJjq{u!u4Gl`g^`2kxgE^ajlWSqtN1?^4u#H2~8n;+Ze%+C4)rgKY*4E%~YOqwt6?q zl5ObSoue{3=-q=XGPSx{fK3^t_!m>OE+S3WS)*PY?jGGMEwT5Mo(t$es7rWIL#9Rl z^h#4_V@~g|S$&@>%uiaLW*WcgRjk@D^rihFF&JR_hY}D(lK#8tcER1Q+Zna)*bg2W_{68 z^LYf1S(J>P#aMZGRVqyjrk%G=x8UOg{wAG*y_WCwFW?WHio{=_0%nR&lce_yCyo@! z7_YQNwUjcohOs&)2%ak!IzN2|B<9YR=Ip(sJl^@s$n1Uq851l~3nohM`Qga;jO{aC7FdUQ4unFbF%6a!Gtb<$xpgZpJ5Gd-U3J> z8wn29&00<>P;`@=I+HrLzKaKmmzFd9X@+O%huz{C_-^NpjJ!mX3DIjngs-Zn$oy&f zklRz~%`b4wBW%ioe}T&Q(bJ?fpk2qW^uR>!&8WEf2QP5}Wv(UMx2cR|U{$;={587? zp0G%vlOG#it- zwruLVt0>$0h6be70TlCqtixjtRSsHE=6ewH0{FfEYz6{7XZ=sV;eYxKDH8Zklj{GkZMX`#XIn|K zGn8Jxp?@eOuqYjWh~NKjJ5=hww;;1Kfx?elWDkyhk>WNrYh=fdUMfXgvHZro8M)W) zvrzUM^V*?FV1^kQ0cq!1NccVY+OFwQCTm~ha=Xw%%J1&i7E%J4%+Zk@?UoBMzrVkJ zDfN(@`EmrQ-EX1gcM=7zeRVcdLL1DU5t8jr3pK8jbyib?&McylY3=F@4X)F5&L%?T zETa*!C*WykSO|0dQTNhB&|j2-2iKV*!`rDB-nxDkgQko2vf4yewHq!(xVDQ~rVDDY z6h_!`PJ9s2VCIUTZ+Bg&bDa{izaboTT{(iY{mQ~e*Y9F46u2&0z`4VGg^+T6v50iqg9)FV=*1Sx6Dm?d+D(6_aC5Ya$-kB_lK1 zFIk3Ed>ylP6sln{jx1{jFF;Pfv;e@es$zW1(eaVUb=F9__Oq5j6}<*Fr9znN4w2RE z_LkKZ69!hLf?yV&2!{3xmh}}=2F|=fi7Z_a@OB-`;)-tu7Q6zCEa4G~?N2OoD*BV5 z-J(mZvMdz1N7lESSVjqSBwKb1TC-F|q_nG976?oyJFAHnuna}mwO_Lg6KG3zR1>+& zN*@{8u3-6A;B)fx2+?-dg~*C_1IyCic@zjtFgrzvD6!;4XtzJL%oiBkpP_*HMZ`lT z=C6_S?Jkx@0>jMq7X{uk%SS*XDUfTwY57s0mHGL_heTF#AuJ0lvO&o-uSR>a$Z1&6o~1hCx)NR9d+q5WXFbu9>-v!; zN(^~n+HL2ApG0cq#cKa3dijp|meL39fg)SIN8HQ|5f_xi^U}3@&k4SbxJi-9JSx* zxxgA6@kHrXUbc4sJ=!BO7 zc*L5L2WMl<$anjf!j;U15xh!wIpbn}e7Al1Nbve@Z*_?LgbVqwSW@Ykt}R9p@V2ijyZZ7kS{yT zfxS#15&g(5N3|6AYoZHhhc>aEghrwhxyIl4SeF8H@$4`ZD~e|&(vegB)zJm!BSM ziRB{15nai3{wA^o97EBo%6LxV74j#41KCpLRc-Hhe=XS}j$uy1Q)!)9A;gS3{}t$`$W-Et<21n?rjmK6q)OvtMnC@oe$tuqRd$&qloDm)4>_TL2xY z#TpaL{{r3|Ko8N{uc}3Rwg@^by26U5BTD#Xv}l+kkRzj51Yv||@0ZY`Vh%_4Lsoe3 zi$piS`W7|w0{)>StSSLcwD7BFF)+{PA7omk#Zwbc`L)QHXCeEBmREQ1^+XfDav9^S zvObK>Y8Bp)sODE7qnlN(Ia-Jt!rKua`Gv_SX60&PxNvcVP@;lgu8dq(wq}3F>H^-C zXy8{W1Lnw!9_U!fBMcC2$ut!B<;&=B6bBSi5Z$l5!ij%DeCU@fqsLKld4vWRMEFds zJ;7tYY#A+%?92T$D`dRCw`?AIat|vwkmqCc~R&LIlk=xAn?4Mj+$9s4iH??9J00 zJo5yaBRZOf>md|)>oyn9C_r;X2Ut(^TE01FMhluP+RwT|AP~L%n#;`~NW|y>ZUu%n z^5$z!G}A>Ej}9YnBLu9saC54eIZg1{yaI=!u=^)8Rd6aJ7^xI7RS9%*Zmzo*zmnC6TSK)Xa??Co!nw6sl^ae7iUv=dU{-?KVbKOQE zY1O|0xq%>I6$!cC+RY!#6!>$Q25DD=@o&B5nzJ*_`;g0{%`oV+aUWuNWC!bom-1$p zPRdm6gZr$SH6&%q_vI}2SK-D9Yu;dKM5caUuFXKzN(!Od+gds=Q@gLoreA1<1^>!h zLOLT8tcfTb(Zv-LhP}C^6EanfPoP;`IIN2`U!foiN5OskHSY^#-4j@nDd40)Iwez0 zv!Kns!l-oD%m>*#I%Btq@|<8@kK9%ADQm`_O#ksivl>q8Yz=&l#< z8u*k-W7zGYQOXmi*Wc_uZbVLxZa4(kQLu;dnUG$O@=$Kfo5nah)K(i$@U16$=r$Hl z4?Ek6qF5({*Hb;z8%s<_%IzU2o(YEaN)N-vQgS&3ro#{HnW||gsMp_mm`NftMtkjT zs;eeg)+0QWB;gr@8g>IlD8{mkehphL)WU@8dYy-!WC`0yl&vy~bK=(eM~|oBgSn`C z>wzARC9@UnV~q0eT~H9sE>0~ePR+fan)@s@|C!M{#vDakpX%lbGpFbp<;lGDK@Yn| zRK|pcQ(=wiWVzF5jol>5X##lyMyK!^#mQ19jEF-TN`2z4Q&5fEWOmso#sODdJz?Zj zR-7I>zOEqlpf(C+I?1O$a)L)+iX~@?jVq!mEQPo;c;yJT}he z>-Qg|V99O=L!-g8{rcn=!n99O2hPYA~M#7%0I?9NqEC?g#P*^=QVdqp`V`N-b zjWKd4s~$A6D?>3F(Ut{cOdQIEM^o+9s|$?i%R(^<4*9}^*X`)4-y6x7y}>+o$Oep| z1EIRX$h52+tc=JT8L+pjMj08Ymlc3@5#{=$B@QDfdn4hpFt8#bS0BUekWj5+bf+wq zF*n%umeD81QfdbV)CD8zvL>(@50ctW&gdf;%!5c6QE`9+1G!%o4_2Y=KZOGInD2}p zR$nzbU-k}c!c)#LdiY4TM{{SySJ=F)2&~6b!Y~kKtB87HbgS$mSc|8KVR+l&p!zVi zcB#zE!K=E-$c!&KQMoH`anQ}K{tdv5>tvKq2kq2L6qG?x&)kvkiA&S?CkuNUs zSy#T*NhtA`Dbi3agbxkc+Mym9+4EH=8j+%RIo4$-ASXzgpn&NFHWL7hF7O2>J|QWb zz<>lmwfxR#tiun~OCv#HrATed;XSMmp_vHwL$v6hxECxBA%UpkSKOj!UeY(RjCCiZ zocILotRl_f4y+}if~e(J1laPT%fmF-*%O#!DKI6JdqV&-ti4$jP(nfNurZd8@ZKA+ zuO|i-Fq!&<5@HAiCq@y>Uz{|o`j^2Yt5YD2%!B~uZP*|Np8<0IjLkXf` z1*E5_ucw%xZ|5wuqQ%tBm=7f3uyp)be(l;izkQ6uwWRX z0pN%_YX_V_v^Z^89jgS(YtS}DmP1AnxM3Jp;;&e*91KAqMiQ_pFnGfg)0}dx05Anf z#a+Wz*sHM61_jg72Vf=y?MN{83G7Y7W7F)Td_ymn3Hgiy4c)?G-H~Ff9;{NrFr!pMhpRYl_&oLu?5%_u8!`&gQDQk#fsHa|6fTlQTSPlz<1xh?# zNA5yM2)~gQd-Lk(3FY-X{}b%$_!Kt}v)f;;4!K_b9x-q4S=~5cx?Vsr$A6jHstLpO z(!XrzC3~9cpc5OYJ6Ym1Qe*FMV&95u^o&dRh8gW?PwY~Gh<;j$`p93055UNX=%B$A zuolq`pS72+&NR|2LtylACDkJn_D+CutCqnrS`J0R!&rM5u&?#YO2GPvBK=`*`=aY5 z?@JPfRqXEw8_x@kJ3K(_6i(5*NSOl?1rX<=(fiIU)n-&o~^2J`RI@?H#FPl+| zwrHlL7F)KYyHk8HEM?Cw9Gz<1Q?>+d*5e;h?I~W;b1xYmS+n;LPD@qqDX`YADl#1I zwzn3pO4aTuvepwSVi~?@FCmt!(9vQZ`7fwi3QHT4Vpg>Qz=h z6kM~vARJ6AK0yVMf*1-?)zk~_>RKci+yQ$bn;xi}`Lk;>9;0Q9K<9mYo8N$!-ebxi_>g@q{FN zRf)d}SGZ4;5Y#DmM<-P8b^^K6-wJ*2xNWrM_V=*T?<()E<|y1F#rt*2SVdPVkLRs{ zJ$M=uGCDP^3M);=%N-##_b20>I*}(}v8hN{^(MF}dWz`J#3j@F51Owc@w&wOh7gkBXcc--K#)$CVV68F{Y|A)Qz3~Q?Gxm{lW`I35=E2EXXm`zmafC_*TJ3Lql?9#FmW;EmXE?+p4;H9M` zoEc}VS(Ia>FHry_8Q?9%X>HMi{xQU@FMyFH0ftxtyVkL31A5p_10h@+XQ5eo-XKn_ zed@I0otU>1olDajE3mDS9phl3=C>2y%BDs6p- zleBemS%=AV(F(^_WZ>;4N$aGGoz3*%nvPnzz4a{cdegbAWLzg{8nt4!RUCLnO(^Rv z6kIKjDjq3~PSGj0m7`lVffj1g{E4w08q-26EL-7$ch%1G$7N4lP}EX8$Nz@;+gpzu z9x)Lb*4;X=z4O_5?aK2@@f+=wsm2v6AT7bhrIwO>+v}$+S5EqeHQXGRb^~1Su<4Q& z<1G_z@8F(hS~=|hyg|=Ov@Cw8!)dyD#gPt@gv;Vg+9jqqR*r4i zgW;drpkpO+@on-q?WvX(8~=)idsY`NCUAW_K6PjXN)Hu(qzV)%gnLW+hMLB&IQ!?R z7yyazjr}*-DTkFS{%I;kNO5SQXlML%`^tI$I2BFgIp`bFZOlpfp%@!qn zla$*tr}R9I)IJ}*?s^fEOz3o(Mti_&qet(!3ek7+R1!TsTewQgC#Sb}PuY2})kcio za+Q=%;_hUce&um<%L$CyCJXD*i$jTXKnhp#;H{0ZU?9H^x#=_y@7g*G%Tf`O_@Z{B zDRB>u+DZ#B6UIrjCr+JGymj)eLT-93v#`U`u1}Ai^s#-cNX`g zFL1p%{_W5sH$04-wA#Kk73jgI7@MKdBSlK`?6j&(o);!1cy=gG&wKbN)@K;?h}$Qk zzL`x)dWa~-XJ|4C%gpqeM}T5xhMt~i{@cE94pTs}SFGOQ-%?)*nJS~l#c6s>T?7J0 z4|b1ZiZ6E}=<#+3hztuo;Dg!Znu-}mzO~6YJ(Ibn7a-c0IIiWEJJjnmQ@y4YAlw*d zb@yTpSFh(x?V1InO@`)(_Oi{qUAr4_UNwPFi#eCl8#L3jmJEg$v`%y^e(|nvj&iTd z4B87;Cp;GCstG1x-I+Qs%Q|Vx_)^WG9Cdm~^m5EZdTG|3w~Px;rbm1*5Yl(Ka*p>Z z&SZG$Dbe{h5bisOnMWplpl9zKFAF7U-sBj~wjA4DmYHy`TS}6=Nhh`M>nE@a^Cq0s zI+A-=Og}P#tWC+?jgy{#6bSS)HlqRX0B%&RkquG1j;n|hzY3HJoTeT;1D|$^Gir2Ei zxMF@5plE~NfB}+^Z+m^|@sGocD>u%HFvY*pyh$%xp7k5@OI_H)C&4Ty+ z*BsBuy`htH`j!Qyh9-q{;9i|$t}j*a%J62PfKhUx_CRi-zEMG;;q5{}qqjG5?}-@} zo;QjU*Zizs&Ms+`Ag;xcyQ1%3&|s)1E}9t6sIzAZUK`$_7c9+v`l0OSwzR2n&4xF` z1rpyxYPaMPSEKwo$K|nkpu^WJl)ipvb^Rrs0mp zIu@2OZ4-Q18|LFq{$&w^>B`=V{j~<_P1Mcp$vMqxsby;{jiXtNs#W~dmkGl9r8`sJ zcYJg!==YLrNR}dQQYCg(MQ`%lZ5X@D{i>In8$r#K;Emmn9+nlaa<&g$qd_+KRz-d* zB*4tVFHZeEPtnLR7(*=I#1IQWJ zZPfbLQ(T(D0_J(DJx~SpUpp^OP-N$EfvU;gB&;eC&8oX|K!{30x>rQeblscYo?Qx$GSOh6@iPwc$ z4|}NX{cHbypuG}E%9kK|Z+?BOdHey-ymT(Z^TVToS4P~%F6HA%e%sl$n7LsWsXyiK zzCJrS=me8}+?^n2@I)K(fSIKuslj~3vAxJ{LhVDG|I+F>sWCRYi3@9_fNoxQd|e=u z*LoV7Li8F-$+0wssRuSavHUx=5%WVPBW#X-K{xNwv-~GWO2H|=TgsRP@8P-fp@)o{ zs(#wIA+Qk$Uc`di4QK5PHkTl#RH#&zxmxw6gab<~uuIfXeS#Sz!KN=eOjy1c7pgUH*OO@B4p3frEiU_g(tx0RG1Ad1sDZ z8jqy=E4=zS*#cm8L#1ZOY2Et$5Lp4*(Jkn=5a1J)j@9@~jzqs04@*Rt0DE%CnSZwb zqd~SF)BXpcgDr?Q#1TLGjSZo&(Cg-b2e116hWohMwY=vDGv>L>eXVusb^Dq4J|nd7 z;5~O&a2KsOpNDMTvt!GCX3Kx%!EcX>&K7AdS;CR!K%1uBedb(Cyi2@4Qz!4WHbCYz zz%=Vu_3 zY6xegPFXqLc~P?YZ{WbH5zYjU67_vGdd9>4TSLKWUQfC?#(AvLyOT3kiVvo873PQj z>-@_s>=AFA_uU_yU?%%vb1iD0)M3eEmh5#G`l;)(5TBu6YlIOur{)q~7FHkxU199o z8h`lThlD@Wq37aJfy0N1X~>fyzMJ)5C%7eCimNJmWZ1)5vPM>x9!$+f1n8= zcxorvI?2hZ)W7z(4fAaRCnc2xN4EL%MI}v`x)fhE4m07k^7b_=}!I1Qiteh zaAf|Ba}P#w;&&AsojH<-X_C0b>ESy|k zZyVyb&hqvf1QzDDx4?&s_r0g|GQr}IOG-c*1jKyQ!LAyxk*XUuz?)8^K6k9wH6s16 z$(Xsf(?ChnbYSOJQfHM?->goNXA;g#&EEe$Z?#xoo=*B@A{qhRP#>dtsV{t1jM(Uz zN01ol<1+>N<3<g|>~LX%Hy4uRrO{){GUg$}EURmf!-w1P=#_&Fp6a{BKR@`)_Iyx^4W zhqHG?&t^XH66`)wsUn1P4!yEU?23}T82OMER;s>K-7vIb6$O2mylDW58L=51jBkA( zH$M!dR*rN>Mj|^Ee-cgz=``MOZbR|nd=!2%>2aisUrkJrE?9fl`&^5e$Gb|(dIn5A zWnYQSD56o6fVFg)g;i|>5f$bTpRbF&>VKokz74IT-L}eu^Hhn&2lSMx)|2PWHP#PD z)Jnlep5oDZYN}gnQwB}@eq|ViofEmx!oC_th8$I$K^08p#ieU;@>%$~|N0D{%Vy-Y zmS(q-+UnnfY0P6`EKh~@YaC1~385et5a^`{LJ^xlw1Q&0^Dgg2--gj;kHDDs_;|t# zm-~bd=-a|Z5*#dP_@>>sU&$w$AKlGRtsUwZj71F9k;{Jd;|=VgnNro2{T=!elLm_6 zOS*uflUYlHCq}9kIBE|~w@*G}-X+xk^8LE>DppNt`_G?j!Lyi*Z&r*q$xqnO*c6QTTms(%B18WlN}lvdX%k*iI|S7cl%B0Yt!YIR$GerE%C z0)E&lkZgP+Ofu{3q^Vh}{h6%C4cU1CY_4&o6S=|3+m>1x+|DAu(Ffsjwd zO!h@eSciv63$kk1YRMQ!l1-Yvh0NqIwZr4aAa(Z#ZickxX*b7H<@LSyy7nY_gc+ka z`rDnGK#?phe2rUXAF?qoGqZpuRhir+1Sd-s*_hBqYXcw+zCvTs zUh>2c9aiEKWf*NzoI`ovrO9V6{t0ba??x|i2*fxS6wXFEIg}iZj zUwM8sh*-*_!M*%IoNOI_K|A4j%-Mh~4GIuZA@b>XXFF7C4DZOaW|F8G@=*j^w$fMZ zoBTtcLQFR6zf5poyW`oUO*t@~l<%tSq|RhsL!W#2>kh21vn7N00&9UG{+Qf-Sk0GIu`8Q8Q)8QZ8|GO2jd@_{2t#4Ag&8MmXhN*P9( z5S7Mwsy+LA?h`7?0=Dh@)YGY{st5@^ww>?m*1ExRTSk3Ffw!=URV7upbTzl_hKk)0 zDO;(b-O*ZCNJGd5b&TR0)pv-M7_R^VG*2$&uRnZxsBK2#KEN(%iT+$R)f7k3a&0{n zb1byQ*A;VS%+4$QA&xUs0OHe=HoNm;m8}PQDpu8Fz9}`+l>EL8zgrjpJx$-5fVFzx zrB8)e#OK?#%pKVNEbEdQ_%c{*{RPDvzk*xmac@C+0k1I($fhgIi+X>a4 zzj|IOb49ktXteVQBNB8hCIykdAJY<|ZObmX_c+wll;m3uhR`Y+ucDf@GEBsgo+3y# zJDhh#5m$*-RlwU68%|sqD{WjAIH-C|2y4*hJYhF`(@n}1_o%{@RO2w27oG0o-uqee zh^S?d$9nsKDACbR#!N&_m*`+`!#av2JdBvY*sD)e1@^7zY9pS_&Z3HNrD}+v`t^lD z44b?OdzQxXiK{;jgr}d1Oh@9aU@zYtyUy_}BmeO+qU9wR%CDm)d;2MNG)Z{5N*%Qj zIk&UP_gZ~fvqJ5QP2HPGTinL8&DS|Wab(RA(IlFsN{hj$*GA79<(rEqSVTXbITHQ6 z^)qrHzJ zafF(6{|)l|!@1d#B21|(`YQZ+2XoMXZm`RWQ@r(pVxhLIba%~_$uP1dhzH7dp5c}3 zm(m;E$W1xXFfw|K;Nu2E#Dw}?eZRT!@;%optJAaQS;|99p(SqB+c?o>%jdpK;|r$E zw!1OwAw3k&@vPNbyneOA(>BRbQp;AvMl1m-em9VHl6>%9n{ji`C`}=x1-V)Mn8-G{ z{P<#WqXoILYxuHl=j-a`Mj7dHQoID!&5!iA=U3(evrzn1a8GHC60)B}eUOSomp4+= z4mh1GR=oGxy(K=UJOJ&Ps-h%X?RhY;uxGS6l~$;1RCu(YuG zHCKeb*mmy9z-S$f5*wwXP6(GIoVd@BW(Ah#S}RFG!7&qEc8B#jL6Mu}oPoNZG3J2V zZt+T4P|ct^ZWqmzIhW}k#Gs);r{rI9vcY14l1rdN<&9TmEHFXmTh^j&MIEKehTuqt zxnD*gL>X}I-os?T^HHE(E@n!`JEqIFE!}7dg`MgNC%Tmd7{AHIi zU7hXp68oFanV7C#DW|PR{%u{UQzBsFL)F(lrdj4b^f!X{lC_EEsc&d6c0{Mtmut^z zs<=UmyHksTNTVNi+Y}ismQ|9CS>$7}c{5ZB7GvL?1W!X5HTQg{)fl%RtFr!St7Gv8 z!NND3MzGq7C+eOx9fHV6httwpbY9|*UL&IG_IjV1XfmT07SsE3w{W@MbI|a4$myN0 zKlz<8@|~1Z!zgO^)>RTA1Gn<1c++~{e6UfY=MNaYgXQI!KEP> z;FfueRQGr;sRTCYoJkw~-BKdj!s-c0t=d;!6Y!NRn?y~$8_5QD30n}m1aGatpPg#( zuu?3;pWVL(QN6}RQf?#N?P*W|5ek1mOfAFF?1)A#3$?}as9%ohRstI7VZ-&vehK}u zaQwE^k*uD-N9EE-x#ItcQSDTg!93Q~SxX6eCRx_|lW<9`D=$*g3@H-lZXmUI-#a|X z;Y{x^%8sxbyStlnuJp1DWu6Y52L*`eRQS$8vlsk!!8IFS8~GRUR?Wjulw9~6X@26S zjK2$w-EkCo(3#xTOe~1Z7hk+3|A!4z;5E-AZsKBE{czwFVbU$OS#{iB&9|raHYK*O zCP2)UqFB}UUGJtcezjEix07!owXIs5oU?liJMr|;5l$Y{bEWpxfmYRL5c?mr9wHax zx6gVln-;0}?!5iYoX^*+4Au3nSZ^8Rf)QLX%e99Z!=JJ#L43vv$JrQA?+(4qxI)Nv zVYImtr505onMCu41Sig++)<*ilBl=Tx4NFNHs0Ah#$m4UjpV+b;J87#0H-s z;8>+x8|VlW8^+rBRAKAW%ByzrscdI>BxG`b+n{KRZB!d)EQdVQ=M@X4sNWC`t&RwR zN)LO+yCY(rD;upNubzC|b^Ox_u$un-;mlQLunO%~m!pN9JYCAD&IBjEb;`#Hja@#> z`xu3=ens1U?C1x?kxw>1&zF*X=0nLh^L?eE!;OyZi|TvbL+IE|zV+zoeB>c^b< zv7UolSAn8-lvQH@li{W~;X#ISL^z3In;F=0I@Ktw=8k}?Q|=3eogc1NOoGk4~LQV_%I6R zqnH3-)DLFYRXWQiS!P30{!!5wIi1KvhH{&!wa<5z%GUSHuVfV3>St?4i^xU7oT^B* zNOCdhXU_BZlX{gw+B$8)R=14erBuK!zGj{E?VRAy?NV6+X__m^+BEoA$h;@LJ?zSR z(z0vbMSMufI_SKWo^&fG&3&j@X>f8bwoJWAn%ofBy&~5+q*EjDe3E>^eB-0HOWAc5 zo3Hl~63=`(Ny_FhkdsS9uqj!1wNTqQB*3%8V*8c#m+m&|wJGy1d5!w;I0eb2`~8Wl zk@FfQXThKDI>kU!(hMhk?LQXWnzBQ`>h;vZiK(_#NMVsnk8uUFsxBa9848>%4xI9o zjh8kp+oN27K1OKx%q!@@Pe*-uh$uY*w2_xZLD2oyJKG7NWo$K&+?v(F&S`=PI`aNY z(>7&xsfeGp@eyn!#Z}9LIu-1>*@bU)&adWyD7b5|_C0V2B==c`S%vez(Ot#6t_!|S z&9a0rfJyKVojI;D%HS)8YG0?Tc2{m=03Qb;kag4))F9$wOK*4~vC_Nw_4xf?5C zJg>oFQPo zZ&VeI_qDz+1scaUn{><+Ygd0h8dpMMb?uJfRRhnPgNNgk2z1)~41ttW@4F@4)4*BQ zk1TkE7!=Ekp65?k1jx=Iq!s@*yE`fCPXP?=im!XzJ$Qyr1ra~)0_Z0d4?symqf0mW zJ);2?g6MTEJrm8($_Vx_FRq;$h%?c)st$olX3cK@SLF{3c2|6{ERQrrxH!`si4`=TBw5|PKw@7wp8vqp@H2@ z`Na#bXZa}0W>h-uR6I~^JY;UU(EJ6bvn1JwTI(U6n8-QWc$?rfykgTCC3TUfp0?LE z;5myx%E$ahSXAjSt;VJWnUeJn{J_@HAknqV??Ysx--ELp1tvLGZ%arRavI3#dh8GVsm zCYomEM^H|q9Msgd}+wcp!-hG1Zne>k#DI(kMQ?gPBmpuU<=)1ejc3oyUx?VPu*XSdg*fP1 zOgfPc^CDg!;%j;U2lztH?YhcHSkC(Q)=)8(R|X- zFy4(p^tdmX50TGe#SX=ck^ZFrkk58YbNNAqooORg*8>DqBnRR~h@f7u*GhIgzc>Ft zkm1ICK*3lCET&LlhhJn5vl(vyO9P1&Px9&ls-E@}rk|4}@7V!%n9kRQ_$tqR>w z&iLQG0=}<^W-XL0mR|{ zg*R-oxR2cD6-WMUYlmF$Lr>yk_~mzNX4-W3id(kGy~@|P%W9o|ZA}_UY?T*T|JK$woa(O;YeaZ^0Ht{YY&kvf+P)?93Z^|!0Z>iWR|p?!f_!f@ z`;Nfe<(YwOUW}adZ7ZGdp}je!T08Av z)N=|V>SDCyKquzA=n@+rNGmD)in$p$m`e59?wf(8@0KVG0oYw*Ru(YE&)>|Nf9x|S zDibsTN@|wLE)4cM>1)f2Cq+r}e^z73K==&zKde*%3}@Pf#*ai6;;W#&YML2?iNIYg zgcNl_Gtao@)W2OkJn^b@vqWlKnUMANZJ9=@)#N>JxNFQAxQ2A7F<?8Ir##WzFOR;Em#m6Jqk3T*snx~dPdpxrSjqWS`S6wp#kO) z=lYPl;mA?)$F@{xlukJP&ICy06uRIBY%2E;Cz&OY$8JKLDQ>Ho9lqid1uvSIOm-sD zRR|$1uWHus5x%$_$4IF#NM$YI99I2^Is4MA+Td35vSt@rd{A+BV9lh@dO!*WY8PnS zIdqn6l@6R*hF4mmb7iEDLaE@Ip;>8~E(+Ys3D@^O0IuM?xsd=I2|rD96GrW-11(7% z+l*w0dU1#;t(-d8TpRFX_I43hDz7{Wb_b?@6v&z5+wv`*i*gVl|%fJ5c}OmI+3|N0(6Np1J96igdPypKiiVNtB; z7axe^2ZK&~?fUK4PwQijv!b%rsvyIRt!0{D1YjJ?0mKNM)sO|HxKItSbpCo;(|vMZ zx$0b1P}5d5_mHcFHgQ$HMX?i9B4OXxUOgoi!%KT(gK z>zp%>BO9gP=CU&>Z_%)E?R-5Px!`25dDV+U<9Y01ex}8%*@V}wvX@JG0FlCxzE&%C zi9K5jw&^vkL-R5RL1q!ZhLeoFQ<2f)!P)7sn{JY20nld=c=%jpZfBA-teDoZt@$a* zq`-Wyg&Mf*+_N~Nqfp5Sz}aW#L~%<;8ZibZ8H~D!dp)w`sdogB&|^(=49J` z0+xjx4#bxr!TH+#!{$3#U9%Z&-@V)Zy}O`n8|-lB&Z=E@Q{dcUwz|TND!RG{oPh-B zh_QDd87W^6w4J;=sthSrEdTu}?Larx$9gwtePaMRg6r9%gOs<&`kbI;s*M>X-O5SR z@kv-&A(tf*$WBrhyfk$8wYg*+z#MWtK5B>V`RZ~KV5(d1w}}G%&uJRI$qiT6U)Qr43-s` znlJ=ypSdTK;V1M;RccqJI%0xiu}pk7$APvHWWw*~zgl0CZ|ME2^;NBK$WvNu(#r74QOw9R%hm>ts`zm zYg&Mfo2j*kQYm(b!ZBn?xaQYoA=<8nPM`AZT|Piq7=IgJM-g)^Ppy*j{L2hdbI!v)=-F66N@{kg4cu%EI&M1dMD5f2|XQhwezxlX>{#&#i2>XuWX1E@UICi9}?9 zbZ5RvfZf2akLzx#&FedZt9DLL7+wt?M26d9L+$GCp33LcU4{x8^har_x^8IJN&?ILm2%Fis_2+r% zf5?6?ipv6~n(c$zLyI??C0~qMmtriN7pU)V+ymMB7}YNz_~(c&9G7kTFAdTih%-W! zB$|=s9(-eGgUs;C{9RcGf_^Iy3zPSJE@Zho%OSqhj15wQIw{p9m-2BjyDqkJoYb{? z8Q1B&Z9?Sr?I-nTt5WtfWO#(s57F>~ zheK)K+^Hj<$QWoHHwYMh4cof9Zb1cwu09KaG zrP>l96{PvL?-kWHj4AciaTE%MLf6-El0RHlmP2CZp14qe3P? z145=iL?6a)q~@Fq>?I(x5ncJwWfAIthzqnulg${iO6aFPKu+TRZ?Lp{VP6C=rz{W3 zq}j1bKG%rj`^q06Sn>BwZVU(eO1jxS*)s8u17*BaymdsnTuXCiR8ftyb)pT9C51un zcTv%;DQ9gRU&H(D`^X&H#KO!RmsDbe20(Q+h)Yv7gn(4vIuwu(*y*n*6S-IaOn5*w$gMZS<~_CO@>&?Jhwhm;4Mt|CM- z=(a0zSqR8Bz$lsP0ef^93dXBMK6xfaxb!6lCF|}GGVPQv^%Q0vJ$?j!Y@}}&^ar@% zkTo_XPPl-x4NiYcKi6;0Zy~Za)Ruy<1EqE_x(j67EF*v08&L03CCFHsNM*=e()%XW z_0Ua>U(e$}@>BSA{pw@T1GG@_|9$66x}t5-NU&9x z@|RPi6z7-#Y~TX_xH1W%KiYF)c_RDcL$H^^Tj3ZMlT#R9QNY>J{U;qTwcx*?UfLfI zX`0LHu9<;QpyI znE@}zR`Q!=omU6RM}%OhB>Z>2nx@srS9=jceS4U<8_TuSDq9>B(oe%Al+vJB!W;0_X+kwi{V& zPtG+3bh2ZVAu*(kGpBp2J#MU^aN`9Xa{?z<0v>6g`SbH^0`)CaegYTfPF2HtQq3KM zg!JSnOKG3l6b0aD*uw5T-PdZ`4Do}Q7h`kbf>m;j*;+=l=hYtk z=@qr9pl=9NH9mN@eEQwU{EqJrHCme*EJL-C(d|TtVj`U4u=N+MT0l3z(u9=Am}Hi| z-5s6dN;f;%C9`fiTosu9h`b8q!*=qS4K`)Hd4&og`7e>`%cJ)wWh$rQEfyxwAp~m4 zx{-k)Zx1S%(j0_+vJ&QA9 zc`M0&7Xj_sg^WqUlCHR#I0*-@&#COjdK%A1n88Fw<@0vsUhU!{?JVA;tZUwIZmD(@ zXTcHrUd=K5f1PY+vGrmB-ta=NJ>lJl7_;D}4=tKieMqOYfd`5+8aYn;YalD*vyOLQ zeeGwLXuC05p`q{*2AY-mx9eCvnW1#Y5@6GjWRN6ks5y}LpT|StR_fqo=AaF>508)8#PvHf+31ho-!%eyy}0SLl1u=-eAzmB z;?<-Z!^MCi&1Uc~?z%69A(G^Ka%bItw|9gz1xX^!(%rE~Z!$_f#+LAET1l5+Pp2fJ z2;Hd*N4Z+o{xD>MMRO_RgGU|W3>k*MiZUw5ytgesu6Y0wRf6Aj!%YN;`#STJL|iUT z0o@3=paw7zp3bXTsKA~T#ZH3f*~kTN5FT%z7eEsupvso z6OZmLOis@MAyFEm8*VFI`m?G*=w)@1rMZs-Uf6XGLrUX=%f-&2Veo~w(-CG7tGwo0 zkEY`jp-6@wXxZ&+snOgB>hNwxu%0?;82W)eo8ykQ`o=-ww=V)yn9dX8EUd!Bt~ys0 zv_N5tp{zC%fb$8z%I-)R08~qzXqgWq6}#y~7Hy>2K>fylm?eO^s#2F`AwL1M>t`k1tVkcJKzE59bg&hL2@){`mr7c2DnLTsGSTJu1{468uDxypGQ& zqZGh^4NY$dCU4{C?78v-Bj#3l5Th2kgVi*Yr0c1(Swa(F$ElkPYeMzlkJkcZgck?m zLw{04#|I>Bn+m#&F9xtu4gl(Ugn{~btg%I7UgeG?K~1-Neobikif`wARL$*L0Ct}0 zmn{mw@Y1bNN9Z>BO@6jO;!L5J>$b2)jxqg&@EYh$u~Ic)AGf z2^bY5hEE#P;M#s4P_TI}SEvi~B>{5ld%wjrKaa%I9}FeUK`YsZ>3N2bL(b53-cq*F zx;@$@?mIhL;F(`qS3Nse2txo4q!N2M_(DsV-nJ?7y)|elZZU|+7A0F$9h8}tD!tFy z=DBA(n_fudK^U@?K901%lEz}fr8sK@^e@Hv;*$9$*uIg|CzK=oq<_<)Q2poo>pV%< z)BJi${|ww_zPPRPV>Rldj*ig3<^&?s)Djk?l*G5SYSxvxJ41aKf<361jRjVP6M$y~ z1CCX_&bs@7h{&T)mPf6Z6Aa*Umdk5>*bEz=W^49Z`_Og~r^HT=D z_Qnk|6o10=scm?19}}MS;YmgnjTx#~`3c__*Rd`O8ia++V>W}?C)9|l97|=VNs%O- z^vnjEU3RNE!YzcI(NZbHl+BoZIhiuJoG~;vyJV=}7>QL;CN#!Ay3sKE%H*t-gI`NP zW~0`I_*hYut+fNuSzD(M=9bG)VkA@*e=1I>y>rbO)a@FIt5OXGc)}hOZf*GW@t?De z8!_w3gG;7vgK90By~xoUqi*zSqDtqvAfXzv>5}CQ?=eNr+A2l*78|yWiDN=OvBRp* z3S=M<*8TaRkZby>D0ok+B6oMd1Nh4d(T&!{D|9mfa4I!8%k?Qcg5Z~?`gJ8lMHk-= z_|hLV{$}tB5rpmKm;;bEr+_ESe2S}K2^x2zEkQwemVlfbc1gATrFG#?@P9bdA&^t` z(=A}tHXXWKl7@C1DJ-xRJeBJLfVo*aC%tqPa8P8=8++&Gq6~P+egaP`r;p?9B*!ExTP^zGEA>0>D}yM3&F1bI znhR*?UH{a%Qud-p3&2xf>W@M~Z6lm|Tp5fEV^oN=(lMRb*(v$rZg{>W@D$S13>|&p z^l&9tBAq-T_8cP~rtA#}FaV)y@iI970~#3s$2)pR@fzPb<~NE|#v425%Gi$(YE+6% zd1-Q!#9zy&OUD!lXsnw#wS=yPFOB^Lz0HcuXCV-c3Zyiq4fNmG3U1yx{4*81>f3kz z17n0i1@OVs`gYeE|NGBwNfQIPP@ACRZ7)t+wYtD;YSQV|fadh4sdS@md@ext#9_#% z3biW`X@;8}l$y8O9h#E&`CaZ*xcV!cv`?L|3>wbY>h^xT+TL5&*^?fVjQaKnVEf_0 zce$YY=(t7smHAaU%=fqD0mwOlVSdQatU2hL21#2_C#JqW$OFx_NQT8fD&!9g9AubI z+oQ%R==Jc!kas@4U0B|mm3u&MiIHWj>-r4qs5n6CRj#zZNHH!Cfq@SoebUkCNy(5=ysa*VWRuj( z6k|x9*gh+8089NVb$`*ZV)63A`FEAiJ5D-+ZqW1{C2$x*cJa={>!ve7@!y9m83Rar zHySV;_vuJE(&SeP4iaJTb+DC>4g+B>^uu^PT)NN;%+l#=r~jj<2g;GWJh8%!@%auR3Av(wUuL0~A zNsztS?sMmFa6^vlgo4Wi46tShRqgwWPH+(;=&Mnuax7=yb))gaW8q`b3d>7(GCUV= z0$mX{?E~Wjiq0^`#(SOf7TN6|8ElsX7O+D ze1B`w8)>z5f|2l>Qv{I@9tIPID< z)Rql$^PdG^+W7Gl`F0eSl$r{yA}Dr&Kr3^cD=L}T^;{gS^`vDmRkt*7t_G(n_$&0C`;qy?UVlFzfJ@Hxh?p4PS|hZU|IHjfYITy<)7<(4dmyZpV*i~6$k(Q z>(1q~KyLODp0OB;HSzzlf^=rAfCmF zoLvgZ2#F^wq7^g(A!SwM1xpVmE_%lCpRi zg<7Y*ZEV$7IW@MiZfRNcXbV9qUNrddc=zu(a1)0?Z*6byz&gB!=#E&IR1etR?ja?(`6$nFCX)?;kH&_mRIW&-hl&ZVn#rR4$t_bXytG<0dR17GuZs z%`J9rX-!DXVg3xc4}Yt?c(rLa`ni8u^X6Q)Q&&Z(>{W8QJu(fN%lFpYLaH=IA^ zd&)QJw_tVKxFz}8Z`8Zz|NNR5*-{Na7s@OoLVE)2CN0(Z_-GFAN6Kys9_Jb?PPO#z z#yVhp{X8F~j!#6pT9&(0%dRH3Z`&U4N&VTieDm-*E6;gB3a-&(7OKHw5!6bz=+?`cOaqJYdg4O zFoyeZAZD9+TAf?LePN{XF{)@>W~n4bSD%}+u8i`XYjvRJ5iu|Bx9K_2g=1RsNU~PB z{c#^xe0|$-pXZ;Emxj+M*$N9T6W4 zT1gW=QYpXK9Uzr?`EOog7UwsU+QGc!u8I^}?b2e}=lPX_iKfaX@A`SB0F)J_CvD?; zH*2*#x$tUTr6T7)L#6MY%xp*>^Les7^79bo>x1M!uV1o>LPTVah6+4=bfV)lJO1)o z`+MkOh>*ndp#<@25tYh-iLRdLIj-oTZ>Nh~^&C*8`0rK)k9$(hWhExG18Ubi!VK0R z5n_LE#aOvc*JiPI)i^SQG4%f8DSm)r|^RGK?uVg+k%Z~gV#)T4(7R$@Zgx~SrdTjw9M z#CSE_m@r+Zy^~u@(f1JWmbT|gC4XG?`)nmMECcLxz_LugYX2Y# z7Yoi7+;6_U%Zd2SgXlUt*l7N=!k&M29 z^?j{M8J@6omp){lkO%pB>-TUG0TX}-B8ZnDEir#S-#Q*-JFxOROufE%QaH1N+Az)h z+w_Zk8)ufE?Z^?**x1hVXH2eoRlrK{x~~?h8*WwsXLnVw^v8>J_um@8(nXFbUU^6d5tv)K0vwUbLKH;z*FgMzsU?%IMXafv1nooUt7+ zQ|0!V#Vim1ulBw(uIa2>H_9L*j4}fPQUnzdN2EwELR1h`1S~^uN+?o;gb*N*C@2g{ z5m7*@iikicQ6WGG5l}+!5PIkV0tqDq2$0;rI&;o@&Ux>B&$*xOhs&3I$ZwOq*Is+A zXRYqzAz*2et2;2a zLY~|p=UaDu?Jx{=?VO0UtI?pR>pGeYPGP@~w=-w*4%(jO_u*j;)+@%2Adk_nmon9! z9niFIpxh%dUH1b^c7l)L&(5Hgm7RR33zT%o1EV1k^~GK&4a^yUhM4?1%Mn@rn#+wdtX=8)aak`7MkGHXr?);2&GKVQ@%WIQew6xoFDGVSUc}9vY zo`~Fit0wC5+mEf{8#aY1XJU7VJHE9t5(Zt26_vQyu66(1Vqzg7&pJVsYE~po3#stl zaKvw9O1~6-DXjArrX4eDG;4H_cUN>ROJCp5{%je0;_4c>kRX4p3mTZYUjIIRR~pO` z7s-G~@O_q&bTs`$CwR7HsXVIbDrmXl&_W8DvxwQXR9hc3q<#@zl54cz|Ls*FagM;`92qUU?+IylfMa(d!z7LTB(0m zU%emxUbq|VOpFexpIgBdPk>5qejb`}Q;61Mw>k6_Tw|bzZ^F*_uOfK+=+Zrk1Ku+k z`c9>|z=n(Ndv6ORfexF$$W6>mtoQ91dbb;Js{iSyF!V=B{Eh+NCE|_s80P|tPUu|> zm0Bc7VJ}}7E;3^Avrk)*^;b+8=y>Tg*hR`*RT%fl8vaXlo}K?YUTV72-o_@F&r6md zvCPH(;A2#dSK>$!ksa_tC;7`uh-4PZdFyrdOh%_x)tJFz+yzC>T|lnw#jn_zInlGz z2b@alfytc*U2_30oB3UJr6(p^I(F;c*)`gjYT5Q|#yM^GVxFs(HfQr~FjOx{V%#Ow z0NN>YhfY(huJ8GLr6=+tElq#~b&2#Zs-s$@(BgOs)x6ZR+MUz@&eAQPI!#CMjm-@#ChRen;ugSK_76yuu z~uYi)e#WwJFNt4QJw~8yYm5$OQw6RZ5|%<&8+*7k7!|rk27}@ zkUSLes9j0TIdf~_wRtUUv(Yr6`V(<9en`*DV{x@r3P@6A7>OTI z(=`U}jJWPnSDX{(;M5^`)gmpqBlU10ePM8={JD%vT*4IBfWzP$>x4*Uze2mf$;DZ) z64R{eqemJh$FtWM9uwA2Lc^?qudPB+4&<+tmk^zG*kX94 z=z$VWVg=yOs&YpQnj%}VpI7Mox?{QRQiA9}E?DVz09U?Anx|vLu z+eG))S>mMW{q1*C*M~}wmF!!p@gHVSrCRwjY<7+NdG&=yO?RtsGAeS06#%aB?_1-; zmpy?u^Lo5O@%&7Yvae!BMq8m2M*tYpt3IF#p-ME7|BZ&aH<&I{0gK|4>Jlg&5G z_7&|-)S7nfu6uZdXJhkKuLr@0cVeKIB6yl%{dVV)omIrdgFkQy?Bf*w0a(tz) zNzU6+>YOUub}0yoLvEOpky7@Z@?E=XmD7gX`w|Y#NIQ@2%wbB>;D5p=d8x0*czz~H z*}tA|oHQNX*wChFN$0JmYy?82nzqFLW!> zH@!-^fep`KKi{{IzOx+jE67k2Ntgrr;icmZ0z+d@j|L6hl^u`ivyK zv#nfxdL9@Fgvwe`rQT~Xu%VSkmGU={v0i;%LvwRfO>IH=(eocVu-2Gj>pN3+$LKM= z&B&9nHlK#1Oj+$%!MB+AH}dhPHjKRbZY&jNuX+Gh9RkqV=c>z`l<*b8`L#;Dz+pWK zGSGNfOMC%3{Gp?^vG(%Y%QMGcAPzh>xT{(0>E2_>PCw<<+J@>@PwMn(Cv|+zija>JphcpRc3_3$EwOlphbXV?7@;Y-u zz2ElC_If_gx|{HENqj1Aq>CaY&^~aR{QPJ8lKK~TPBDwVW}P)m&6E5f?e1EfPAVT9 z#n>JPf{?#NDIBe$t+q$SHQmKp1n)&Ab&*K)t4Ex#Ug;(31P3kXXdtYLVS_m>jJBOr zVK68wlQ=Pr$_FI*{Pe8?DW6x8`+wT~byWW2T7txovc|DDJs-ugZoxbfe2Y$+;n#5- zU0lVNX>e|?oH?i(-#sGtyGaNF^|zoD!gcBCU*}iiOk2iwH_j=vw{Pbul>$g&k)(Ejl<K6MDp%nSOVVf2kO}LC6o_=AZaQ6tD&ZYpq!x$IEgA zpFHjm8>yPiHHt^^5$xw*@5krJgiP{%)?*{ycg@AlnK+er5VDZ(7Ow2Q05;laisvxU zeRHu!Kbu8Um-@V0Q@NWW?{7{(YpUtQmqL{7 z?01G`+PBxSabUz)2al4o-S#KwJ5l6^ZMp0hXV&l+BCV`W-DBwY^<#*b;JA_+{ik>@ zIu-4dx`n**2~=^Dj-5*Rq(TY^gZXf;2&|6z`%Rh<+w$UqF$@oEzgNswsz8~NhW|VO z9;X)_FGNekwO{@dr$0jRM-dg&z~wgtij`Fgng{M^NK2nRt^n__&umurN!3PH-!@r@ zmBRqEYGse8TEJTDYf($~kg7bvzJFM+x}jb+O1>_2-Ovut_3WOW(W4zg&VAg&ciKty zo=ek#l&s2P8%&Pke!6VH(K6Gvs;!$H_Md#+nN#3rw9Cbfs+lj7c=dlBmE5|yc4k;p zE#USb_f^*PyF;~Bj#K~1V8PTBQsN#cMc6XkWFO?f#*`if_}ZuY%lzc%*8T9&llCQaZM~joI;4p$h2#i_Jb@~JmmicVG+SMr zo&&DcQ{x8EV$X456NMCXlEa>5Gw3gy?#sKgHjVlCh&55)bn(SBp*ujwDxnslFtjtt zPvetst5GsO5cIa)rtT^z!y&-@@EK5)kIKE#FL1tuRli=hkLgPDALM>(z);D38EbPn zw&3<>Zefe}tmhkg-kE?oMH=P(jloVHv#u8ejW&!E@OGBjn)<&*bnA?oB+!So)*#!| zp@~rj*VJn7Xsh!&u2N({X)#lK&+>;suFZ&>DN{`*BS}~IsO{{4s`Y`PveoX*eYua) z)$`Za=WC}bj}ks_3=4S7$Y!=!NYp@Vn@cFB?+`rlcE5yueHLo%=KzhDqrrUo9xU;j zRq7_@P__k>Dhr3W4lB{#dL=uglB9+AegNg$CFMnvH=rUzEX-2Ejtdu|NJL39WwNe~g3i`v@Qj`1M($|I%;c;^z;1f%J<%d%pFckE z$W)?1>p0m&&+%#KJZTtt=!jgl4Q#H46H=^%8`#9Q^=nMn`5cviUrU8WwJ6JvB}0ucoD9ptSFYW19dC^tqvZHm4_@ zbZ~L2@n!8)bw#~Mh^E6p9$lVHmVWLavuF2qV&6sz!|VIf?^+d`)_xi3jlU3p+~E< z%Kyk3Et<#0tUYMzl3C1n0S;-2)>7J9CL=%_b|dUJDY7v^^5bEU)x|N**}EPBpcn&E z)^;avQc$bu&MTZl;cKumF_+mK9aQAw_~tz03E3(9s|K7O-E(qn<7S{m3QsmTHFb~w zBaSRdIrHwf!?LK)-Kn^ki4;~;H}lo=MW?S)HO_H6S$5QSSt+cZ?M#DA)tsKKmyu(x z`|n4Fa-M`h2a`!s0yxBdwShvd;nD@`nM^Qu znAx9h|LJlo5c(^_8=eWH3WY$?S608-XYJoj!d`q-vaj;Nfi_*qj`ey$X0}ImHyI1T z)+9nS+}&K1c|H)jC}DuJYF_yA%YAN(o_EPs;I*Zpjj`^D#_1+v4gUC2-EnX%+i$j2 zy3N`2lZpKd=4M~Y63g_+dDV8TSi92DPIP3942Zh5`q&T3mYzDggQA3IM%1klgVll`9#EolTc;G?$c|0(-!GB) z!+m@*yAAtvEr|CB{vF2rPvi`zc>Zaz$(DLVuM=4Voin3ACKqjv4~=(JV=Fm|8zt2Q z_ons|4e-XN5l=8>Qzp;qVvVHsK#DG;X+O~t(38`Zb>rMC87U77qVhFQ2d#U<(7%GR z7ps&Bur+qdyp{$H?i?E0!cLL1W=f8%Y(%-uL@QS9P|#d0i%OXi?y}(2*!;TZ8^VUx z`?$xWrT%n5wwa}+hB!@5pxOE3R@?M}``jr*UfhOrd8o0A0jF6RyjC{}TTf40XQLs> zZhvGw{Z;10PHS4)%sXd1p`XT}^Gn+|Q5O)Y`aa`2-W^JKHQ@d*Yf#uyg(QTijHaySPe++{I9U4(nZY%GkxC7T6x+3g;>;^?9g{g0wF`PZUF$t;7*AuS7ZiA@_V2xP z8eHn>@L^;H*IeJB0Z`Y%8ic9J+lDbI4BHxa)?dhXOYgMhDmS?}RAXZAxbw+ayH8h% z`L-p3>UK9i-n2Vz^cEhlAz`pU*0T{Cxb8Y!6|yn*p>$$>81e|;Bmzo_Rd3Yr&ihLe zI}n1JaESMY{RXng%dux|2`9XS-2eA-1;k&2wY za=+2qdc2?vQLV#XY-D>Xp%zlJm|ea_?;h$f^%8@Ry$>K-rhWmm)&Tq&L@%J>`z4sB;#N0pD6$nq{O#j_r{O+gDW( zm19gy9p%xk*#P+^cb}O_LFuZ=lV9<@LCT(G?AdYaBPZiR3R`1c1dD!`IM)uqdoDiP zFZif4^+*zH_b+q_Y$9fa$Ht=om_0`-{mcfa{pv4Ly#lA5LPuF=V?=pKReYs7R&g4n zlXd#{(^0#@Lj-Q~*d-f^caL?iuHFh`4@S*WV-X)=RLSQbGz!*cfZHXRQ|mG1Gf&`x zw=?sj7`OtgN38zTdFzgAn+q7uN4CtuOE$ijvJ|dO6NWBRVV(N-kB#6$I<#i1*M}Q` zFg$4VW~Fb;I||^Oj@^pBHp;F3?wtOl$0@$>KzOr#Cx6P73~D>vS=8ylj zkGth;n2n^z>qUT*901K*i);Fb98S&2R0N#>pcvgy?Ap*-<(i4RU#Shx9apVpO)USi zyzAWP?lL|ryUG)rLu(xP#Fy;ZlXf77*WAVxQ~4jhssjuzzD^xm=KUPQ${JsDZbi0~ zp93&T2tJ}*E)A9bb9!-Qx44j;`ik#} zM^)>McI9+sgN!ytOuCl5ma@2dgPcUN2E(6Epe4Zs=?d z?IL+VU?Sm!MQtM&0%M3fgAyGBQ9Q%pQI&4D5-l>Qb_5U`lJJw$n_w&bCia{ zmlwfRW^o*6;bZLZ(#D1D7K8@rqWP$Zx&k@(_Qh(G@<}(!8GF%l1w)a=&3b55Ke3!t z-Ysa3*Vr72mvPXew`mD`w1_QU&cr@^0n!e8rp0Un2y%l*%dUI9CPd~qFYC=B?!wk? z?pbasEWs3gLqs_;+&5G)eROcv-@0Pme=vj!K&4}+!nu$0yqKKz66Fk}9sLqu>igWF zy}qNmAvu&+^i=KzPI`*;OpZB!uIP}S%|AlAlfdH-$eqeHl=OA4O&+{8d{dc$@jd%t zq#LKaNioeD=J+j_Ju0bLFDiNRO=tcYvSVbWzd(ZcUPE0B+Bs{Y>P6UQz)!=iuj8nZ zIQiLlC57}VL9YK=s#A6rUSWfz*T9SBOrbS&M`Y2HKFbkD^3{?{0rzaEeUZ`%l%o%v zEKaYWkBfIHbABNIOQ5h-uLL|$lGW5_uRx2iWyVnn?JZpq(!hz4MwAs8_=Wz8THkd@Q$KJW?_C-Juuo z42z@%lz}#<`~EA`e`rQ-hw3_o_n4u@VH1xJxS@6xrtksiYKQ|hMsA^_VyR8%z|bf@ z>`uMCSYWyy!F9AtP?Ye)jdw`x28HepjdI5{Pjv3acxXAgSf3Bxe?Q53^Dn_Adz|Ue z4rsdJ$1?aHcnaLNxT^njDA#>7ET5`4q`7uVrY7^>!%F|>+pxS@+j3v`>Cbf`8ngzj zQ$?t^J|E?*-N}wULh>MKy=pG6Y?RClPnqhskk;tC>THuQE*{=PS`mlcZ28^XdD*V-O^s^%6vC5A#h*8 z0PUDAVp5rN^FJjagyq$D*XuKW1cPGjibK?BN2*p;MU#bA_O@}>O}&$|+dB&$<>t!E z=6(Cpi_i3Lv5sYH6r~}%bp+7n6?3?Sw^szjteW+McAkmO+QdWSm%yGE#w6QCfYsZ* zhvz>qO-X|s^I-7n_TCLNezQc&3VqdJU9Z)*6xNr=UAQ;%I1GngYvaw%!24_u6!JL- zwvo|L*bOY7dk2b9l`g$RP+7B<8RpYRUyDx%^%W=NB*cuq(5-pi zt!iuVhYk>i4sJ=B(^DjNeJt`-bDL}TRVAM96zmFD)#JW@y?Zlh!vG&+i?B|^pU8D% zems&9SM}Rbaq7U;?D%c>d!cW>ekR4kh1HmC4yJ(w>V`K;{d;0%cy&r}^u`Hs@Xxx5 zwD3{Ulp?2rzw&Ug+f_zmv%JU~9%m*_g3Pb!0E54oJogc|DJ4CX6YR!Rjhu;gz#wD8(aXTj%^7&Ad^#?FrvnLJ$;GtAkq@|if6qwj z#~JdiS>pI^#CCU)Ov)6LWbmJG50vo>td%7bb%SP#RI9Thx-2tE*7UgP@o2a#(N4%# zNJolk9N6I_!*xn&P~^o8S{6FqVB>QMIoZ^4pWawdlQzlekL5HfD)@$Lx?|a7I)ttG z(kFiA3v~d+XqVZ+nfwF{5)eF%*nJZzk{x`Owc@G*D2Yh zuU2kOT$i2Y_p_+>bJ&_KQ>4V9q9WH+v?cdk9@8n`$*h-DrpeamudvBsOUj&8Kxpy? zq%n1u&!&+cKLex29LIMD4~(ghBGg!51g}O_T&g!WXi{U~(YH9_r_Xs=omvWj-EMPI zW`}k~M&}5oNatL|WoiyBBaW}1C$!tsW*)=CxSuBTM8t;!k9I|j{n@9(x6p>fI4ONA z97yNbm8EIwvMUd?8y@-j=^|`Vq>yGgP+=8@JYKe%wO>}WNR#x809)kwUBT;*1*I?g ziFWWm@U*<0!Ef4?v&8?caM7YfH}WbK_!jK}5bMBe22>6(4CO>7r#tZhHa@*Ap?q)* z6ZzZn=EC%|veO5p#dk45c-$}nnMc!)SDZ_l{S8+JGz?<{fci8P`857ATd{ zE#Lp3=2*C4XoGE4JVbzf!b)tZ<~H5?_wb*ph-E=@u(dX**`FwbNVV(aJr6zO35(ql z%4o#9QyaMct1yzHO?9VKOH(?8;a#q6u}<6{i1t>*(fj$Fxj8zbn^1g2{M1eMK+A5w z#3C3daY*eQUzB6EDSZoyQG+Wj@r}ONgE@~1{q#qQGViI-%A7a8)!dB0NuInt{PZJ* zlyCLMH^_YF4HnNk*PjCcrc-e!=Qb|Y(8hn?g4X@zHf*jbIQZ@i*<}<%zG!yqAT;%E z{LFM4Rzm`AyS!-rz^~tX;frxOeqX-WD-lc0miK++KxQxyX*Iz;P zSJZt+KHcN<_@bM|YFiwsK;6ihz|tnkY1b@Tj?i>=?yL$XsbzJ0x;l2MVRgM$yp!;G zGoo~9JU}zbx=92o_$t~P|FQUq_~*q>V9dWNe*RTXzDQXFR4VCI4#b$$_)bXp>a_v* zDfat?5X1Q^J*(osLi!x_^?=H*Atn;FLm_c@KTC$jP6;zDF!Z557#;pQ_~%eaUzXOV zA$3J(=9*{*ytXor1gg^~Ibm^Q({Xe@sclGhwhS4*f&dDkyHZH!;!E{~=o52smW6(v zIIq>CK+U@v*hO6K&TVJ0!hJ|{K(&&9Lg*3Cz_&MCUvz2#{ItI-_Gcb%X^l&e2etk0 zpFIm}OYK>w+I@u*oyhOw{+>3i8xZ!i3_W+lAjbnNoK{_7sisiI;$$sD8fG;hN3lnXEr=NMW z5K2Rebdqm@Nlx|{_u-9_5dXEbt(mJ&kZNR6-t47`k5;~+d-|UZ$PP;4j!Mf8LTSbp?4&}m_of%TQN)+zojuJ6pedi|+JO7$_ zx%(OCNXeeuWqXD4ndv#)WqQAJIPl`H>0~SRfCaH+r?VpqsfnwOXltZJiL@K=pp1V1nm?J24`S%)tIDg&2VAE53$?|x#z^tA6|J;b z3-^W}=l2O(r*UnU^e5s`9=j?95F#ld+?bb|+OS83WK0$+LPG66%1>{wk1!oRUh*xe zE=IM)C8R^H?C6x+WwT734{P0?EznXp#E)PO|2KF}|IR|g&i_Xi+BMm!{>i01_x8cBRq1x8wC$L}kvi?&^7K%L0z4OGBM=-J#uoO+EXgi^1q$R7SXG zTGO-C1M+l4|D+U;e^9ex^0OT801QvPrrY58*he-$eLit=kII+9{>SzT?$?^ZI^5~Z zTadWx0IhE*+;=GI9PWT0{OCNl{B}oFCfoNMt8rkXzD9;FnTkCPv79zJa#0FZX8!_v zdKJziZ_0^~gt;{SjjXhM|pTF)wF{Q^5PkqR015l54b^d#xCmn^9S$y=O_ z)yc0x#Tt>266%NK)hy$0H!EBdfRe4f?0vdPc&iLsZXvW{|y z!*tvZB1L)_LPb0(gpo@J#1|_NRA7k#yi+0z=1v4LW7E=W|Re z)*1(0XR*sI?ey_}U6BAcGFj%_&Y;^7<@rBYR7JE3NeC#*Zhn#MG0bd;NF;fg}3FC&q!9^rW{_B&cr^2|1dg2o>5ZI&z}0= zHkV|WJ;H6kk}$8#^KW|B$rf&W_l8|YlHyuWB<()=FK2Shx< z-DyZTyQpv{!6VBl4E5$wjmSbmYnl3Pvo}p^P#Yi$w!efFu6u#GkErxYP7a=y3~*C7 z{%7plzd6%Z`$}FNRC3y4c{Kacdgw{^nqRzK9eQh;;GQOFOK0rZgeM zN?IW0XbFn%VPjcqtk-7~cN2F}4JR^zkHpKJ^~AC@B-6(dGNh25vEJH%N1Z#z>A6_u z+%i^y_`jvh4@xqv#J5M@U(!kmTjMMgb`V{z5DGPmwMZ`UZC8uf*YSn#c5-_*Zj}d( zsEp(L0IHZRtAT)MMHWJmdZQlEX$H)%VH!#=EArp!h&EoqM|>my3oQ;tWZJXnD-ol& zOXYtFifXrMbo!yl&l(U3=#60Gw)j!qpke!YT>P^O1a&fRdU^F=5OhW8qwWEkz?#-v%Q)b3ePy2NSg@08q3C(QvxO9q=t_5nM&vCq6eq6^T~pRZCR2fEwfamB%G7YScq9(Xc9SSXuyvGLoX(GPfp6; zWINdsFA<~ajg!N%D@#zRR^;wiXQ&e-o;L#vSei$IZ^Z;z0k!c;17u!2{&s@cA~Ryw zsgx$bLe(DZ6c@;g`e9bzGMBt5HOV(>7$0g{So(oLi%nB;QsK4YfYRnM8p}z{lbUB- z!5c2k3_DId9SM`wHr(m`$9|$ZfM52#sf5XDqiBHx7#Nbfe$adC(F<_CC2^UOJ6P+h zCC|ezS%0$cqBn}5lzy!ijUZpDc6w3!^4AQ(TH6Wg-hb?N`tan(#C{#Z2QZo&m!60! z+l2*lAluTzIIeSFzqLJ4Z@A%$=$c*Yw%g?No+Li0YSeDkIxRj-TIZ0?bVxKr`;g9| zn4d~g#><4O<3G?W#j6`4$;jm)!S+2C=RmVIursNUJsH?`oBJ8YpkIs(z|5`JvL$cD zt|$joOaL8Qc2a(bS6vT`6T7m+|4bRzI9x3qNp@e>U2g^5|F@ne5b4{SoZtWce-|R? z|F>U$??nE8td%u}%LkjyEIHi+Ne2{FF7T2~pzEDLH(f}88}I>ARXMApcveMGRs9cD xRb4d|T{RsA6%}0-l@G*{vHvi@7wYQi9`e5*P(LZ=^6e;GxnyoseDQX~{{r`loACeu diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index 6cd0e4df1e..b727940caf 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -57,7 +57,6 @@ export type ApiUnion = | 'mergeMap' | 'mergeMapTo' | 'mergeScan' - | 'multicast' | 'NEVER' | 'Observable' | 'observeOn' diff --git a/docs_app/tools/decision-tree-generator/src/tree.yml b/docs_app/tools/decision-tree-generator/src/tree.yml index fccbee77cd..10805e02fc 100644 --- a/docs_app/tools/decision-tree-generator/src/tree.yml +++ b/docs_app/tools/decision-tree-generator/src/tree.yml @@ -258,7 +258,7 @@ - label: connectable - label: using a specific subject implementation children: - - label: multicast + - label: share - label: when an error occurs children: - label: I want to start a new Observable diff --git a/spec-dtslint/operators/multicast-spec.ts b/spec-dtslint/operators/multicast-spec.ts deleted file mode 100644 index 4be93fbdd3..0000000000 --- a/spec-dtslint/operators/multicast-spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { of, Subject, Observable } from 'rxjs'; -import { multicast } from 'rxjs/operators'; - -it('should infer correctly', () => { - const o = of(1, 2, 3).pipe(multicast(new Subject())); // $ExpectType Observable - const p = of(1, 2, 3).pipe(multicast(() => new Subject())); // $ExpectType Observable -}); - -it('should be possible to use a this with in a SubjectFactory', () => { - const o = of(1, 2, 3).pipe(multicast(function(this: Observable) { return new Subject(); })); // $ExpectType Observable -}); - -it('should be possible to use a selector', () => { - const o = of(1, 2, 3).pipe(multicast(new Subject(), p => p)); // $ExpectType Observable - const p = of(1, 2, 3).pipe(multicast(new Subject(), p => of('foo'))); // $ExpectType Observable - const q = of(1, 2, 3).pipe(multicast(() => new Subject(), p => p)); // $ExpectType Observable - const r = of(1, 2, 3).pipe(multicast(() => new Subject(), p => of('foo'))); // $ExpectType Observable -}); - -it('should support union types', () => { - const o = of(1, 2, 3).pipe(multicast(new Subject(), p => Math.random() > 0.5 ? of(123) : of('foo'))); // $ExpectType Observable - const p = of(1, 2, 3).pipe(multicast(() => new Subject(), p => Math.random() > 0.5 ? of(123) : of('foo'))); // $ExpectType Observable -}); - -it('should enforce types', () => { - const p = of(1, 2, 3).pipe(multicast()); // $ExpectError -}); - -it('should enforce Subject type', () => { - const o = of(1, 2, 3).pipe(multicast('foo')); // $ExpectError - const p = of(1, 2, 3).pipe(multicast(new Subject())); // $ExpectError -}); - -it('should enforce SubjectFactory type', () => { - const p = of(1, 2, 3).pipe(multicast('foo')); // $ExpectError - const q = of(1, 2, 3).pipe(multicast(() => new Subject())); // $ExpectError -}); - -it('should enforce the selector type', () => { - const o = of(1, 2, 3).pipe(multicast(() => new Subject(), 5)); // $ExpectError - const p = of(1, 2, 3).pipe(multicast(() => new Subject(), (p: string) => 5)); // $ExpectError -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index b35b2d2a97..f1b09324d5 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, multicast, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; +import { map, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -759,32 +759,6 @@ describe('Observable.lift', () => { ); }); - it('should compose through multicast and refCount', (done) => { - const result = new MyCustomObservable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); - }).pipe( - multicast(() => new Subject()), - refCount(), - map((x) => 10 * x) - ); - - expect(result instanceof MyCustomObservable).to.be.true; - - const expected = [10, 20, 30]; - - result.subscribe( - { next: function (x) { - expect(x).to.equal(expected.shift()); - }, error: () => { - done(new Error('should not be called')); - }, complete: () => { - done(); - } } - ); - }); it('should composes Subjects in the simple case', () => { const subject = new Subject(); @@ -840,70 +814,6 @@ describe('Observable.lift', () => { expect(emitted2).to.deep.equal([0, 10, 20]); }); - /** - * This section outlines one of the reasons that we need to get rid of operators that return - * Connectable observable. Likewise it also reveals a slight design flaw in `lift`. It - * probably should have never tried to compose through the Subject's observer methods. - * If you're a user and you're reading this... NEVER try to use this feature, it's likely - * to go away at some point. - * - * The problem is that you can have the Subject parts, or you can have the ConnectableObservable parts, - * but you can't have both. - * - * NOTE: We can remove this in version 8 or 9, because we're getting rid of operators that - * return `ConnectableObservable`. :tada: - */ - describe.skip('The lift through Connectable gaff', () => { - it('should compose through multicast and refCount, even if it is a Subject', () => { - const subject = new Subject(); - - const result = subject.pipe( - multicast(() => new Subject()), - refCount(), - map((x) => 10 * x) - ) as any as Subject; // Yes, this is correct. - - expect(result instanceof Subject).to.be.true; - - const emitted: any[] = []; - result.subscribe(value => emitted.push(value)); - - result.next(10); - result.next(20); - result.next(30); - - expect(emitted).to.deep.equal([100, 200, 300]); - }); - }); - - it('should compose through multicast with selector function', (done) => { - const result = new MyCustomObservable((observer) => { - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); - }).pipe( - multicast( - () => new Subject(), - (shared) => shared.pipe(map((x) => 10 * x)) - ) - ); - - expect(result instanceof MyCustomObservable).to.be.true; - - const expected = [10, 20, 30]; - - result.subscribe( - { next: function (x) { - expect(x).to.equal(expected.shift()); - }, error: () => { - done(new Error('should not be called')); - }, complete: () => { - done(); - } } - ); - }); - it('should compose through combineLatestWith', () => { rxTestScheduler.run(({ cold, expectObservable }) => { const e1 = cold(' -a--b-----c-d-e-|'); diff --git a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts b/spec/deprecation-equivalents/multicasting-deprecations-spec.ts deleted file mode 100644 index e776ea9e10..0000000000 --- a/spec/deprecation-equivalents/multicasting-deprecations-spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** @prettier */ -import { Observable, ConnectableObservable, connectable, of, AsyncSubject, BehaviorSubject, ReplaySubject, Subject, merge } from 'rxjs'; -import { connect, share, multicast, refCount, repeat, retry } from 'rxjs/operators'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -describe('multicasting equivalent tests', () => { - let rxTest: TestScheduler; - - beforeEach(() => { - rxTest = new TestScheduler(observableMatcher); - }); - - testEquivalents( - 'multicast(() => new Subject()), refCount() and share()', - (source) => - source.pipe( - multicast(() => new Subject()), - refCount() - ), - (source) => source.pipe(share()) - ); - - testEquivalents( - 'multicast(new Subject()), refCount() and share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })', - (source) => source.pipe(multicast(new Subject()), refCount()), - (source) => source.pipe(share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })) - ); - - /** - * Used to test a variety of scenarios with multicast operators that should be equivalent. - * @param name The name to add to the test output - * @param oldExpression The old expression we're saying matches the updated expression - * @param updatedExpression The updated expression we're telling people to use instead. - */ - function testEquivalents( - name: string, - oldExpression: (source: Observable) => Observable, - updatedExpression: (source: Observable) => Observable - ) { - it(`should be equivalent for ${name} for async sources`, () => { - rxTest.run(({ cold, expectObservable }) => { - const source = cold('----a---b---c----d---e----|'); - const old = oldExpression(source); - const updated = updatedExpression(source); - expectObservable(updated).toEqual(old); - }); - }); - - it(`should be equivalent for ${name} for async sources that repeat`, () => { - rxTest.run(({ cold, expectObservable }) => { - const source = cold('----a---b---c----d---e----|'); - const old = oldExpression(source).pipe(repeat(3)); - const updated = updatedExpression(source).pipe(repeat(3)); - expectObservable(updated).toEqual(old); - }); - }); - - it(`should be equivalent for ${name} for async sources that retry`, () => { - rxTest.run(({ cold, expectObservable }) => { - const source = cold('----a---b---c----d---e----#'); - const old = oldExpression(source).pipe(retry(3)); - const updated = updatedExpression(source).pipe(retry(3)); - expectObservable(updated).toEqual(old); - }); - }); - - it(`should be equivalent for ${name} for async sources`, () => { - rxTest.run(({ expectObservable }) => { - const source = of('a', 'b', 'c'); - const old = oldExpression(source); - const updated = updatedExpression(source); - expectObservable(updated).toEqual(old); - }); - }); - - it(`should be equivalent for ${name} for async sources that repeat`, () => { - rxTest.run(({ expectObservable }) => { - const source = of('a', 'b', 'c'); - const old = oldExpression(source).pipe(repeat(3)); - const updated = updatedExpression(source).pipe(repeat(3)); - expectObservable(updated).toEqual(old); - }); - }); - - it(`should be equivalent for ${name} for async sources that retry`, () => { - rxTest.run(({ expectObservable }) => { - const source = of('a', 'b', 'c'); - const old = oldExpression(source).pipe(retry(3)); - const updated = updatedExpression(source).pipe(retry(3)); - expectObservable(updated).toEqual(old); - }); - }); - } -}); diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 2349cb9072..d73bcf6125 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -126,7 +126,6 @@ describe('index', () => { expect(index.mergeScan).to.exist; expect(index.mergeWith).to.exist; expect(index.min).to.exist; - expect(index.multicast).to.exist; expect(index.observeOn).to.exist; expect(index.pairwise).to.exist; expect(index.pluck).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index 4bd493b58f..25143646fb 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -49,7 +49,6 @@ describe('operators/index', () => { expect(index.mergeMapTo).to.exist; expect(index.mergeScan).to.exist; expect(index.min).to.exist; - expect(index.multicast).to.exist; expect(index.observeOn).to.exist; expect(index.pairwise).to.exist; expect(index.partition).to.exist; diff --git a/spec/operators/multicast-spec.ts b/spec/operators/multicast-spec.ts deleted file mode 100644 index f4b1a31f72..0000000000 --- a/spec/operators/multicast-spec.ts +++ /dev/null @@ -1,821 +0,0 @@ -import { expect } from 'chai'; -import { multicast, tap, mergeMapTo, takeLast, mergeMap, refCount, retry, repeat, switchMap, map, take } from 'rxjs/operators'; -import { Subject, ReplaySubject, of, ConnectableObservable, zip, concat, Subscription, Observable, from } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {multicast} */ -describe('multicast', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should mirror a simple source Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' --1-2---3-4--5-|'); - const e1subs = ' ^--------------!'; - const expected = '--1-2---3-4--5-|'; - - const result = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - result.connect(); - }); - }); - - it('should accept Subjects', (done) => { - const expected = [1, 2, 3, 4]; - - const connectable = of(1, 2, 3, 4).pipe(multicast(new Subject())) as ConnectableObservable; - - connectable.subscribe({ - next: (x) => { - expect(x).to.equal(expected.shift()); - }, - error: () => { - done(new Error('should not be called')); - }, - complete: () => { - done(); - }, - }); - - connectable.connect(); - }); - - it('should multicast a ConnectableObservable', (done) => { - const expected = [1, 2, 3, 4]; - - const source = new Subject(); - const connectable = source.pipe(multicast(new Subject())) as ConnectableObservable; - const replayed = connectable.pipe(multicast(new ReplaySubject())) as ConnectableObservable; - - connectable.connect(); - replayed.connect(); - - source.next(1); - source.next(2); - source.next(3); - source.next(4); - source.complete(); - - replayed - .pipe( - tap({ - next(x) { - expect(x).to.equal(expected.shift()); - }, - complete() { - expect(expected.length).to.equal(0); - }, - }) - ) - .subscribe({ error: done, complete: done }); - }); - - it('should accept Subject factory functions', (done) => { - const expected = [1, 2, 3, 4]; - - const connectable = of(1, 2, 3, 4).pipe(multicast(() => new Subject())) as ConnectableObservable; - - connectable.subscribe({ - next: (x) => { - expect(x).to.equal(expected.shift()); - }, - error: () => { - done(new Error('should not be called')); - }, - complete: () => { - done(); - }, - }); - - connectable.connect(); - }); - - it('should accept a multicast selector and connect to a hot source for each subscriber', () => { - testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - const selector = (x: Observable) => zip(x, x).pipe(map(([a, b]) => (parseInt(a) + parseInt(b)).toString())); - - const e1 = hot(' -1-2-3----4-|'); - // prettier-ignore - const e1subs = [ - ' ^-----------!', - ' ----^-------!', - ' --------^---!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory, selector)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -2-4-6----8-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----6----8-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ----------8-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should accept a multicast selector and connect to a cold source for each subscriber', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - const selector = (x: Observable) => zip(x, x).pipe(map(([a, b]) => (parseInt(a) + parseInt(b)).toString())); - - const e1 = cold(' -1-2-3----4-| '); - // -1-2-3----4-| - // -1-2-3----4-| - const e1subs = [ - ' ^-----------! ', - ' ----^-----------! ', - ' --------^-----------!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory, selector)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -2-4-6----8-| '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----2-4-6----8-| '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ---------2-4-6----8-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it("should accept a multicast selector and respect the subject's messaging semantics", () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new ReplaySubject(1); - const selector = (x: Observable) => concat(x, x.pipe(takeLast(1))); - - const e1 = cold(' -1-2-3----4-| '); - // (4|) - // -1-2-3----4-| - // (4|) - // -1-2-3----4-| - // (4|) - const e1subs = [ - ' ^-----------! ', - ' ----^-----------! ', - ' --------^-----------! ', - ]; - const multicasted = e1.pipe(multicast(subjectFactory, selector)); - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -1-2-3----4-(4|) '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----1-2-3----4-(4|) '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ---------1-2-3----4-(4|)'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should do nothing if connect is not called, despite subscriptions', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' --1-2---3-4--5-|'); - const e1subs: string[] = []; - const expected = '----------------'; - const multicasted = e1.pipe(multicast(() => new Subject())); - - expectObservable(multicasted).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should multicast the same values to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold(' -1-2-3----4-|'); - const e1subs = ' ^-----------!'; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -1-2-3----4-|'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----3----4-|'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ----------4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - multicasted.connect(); - }); - }); - - it('should multicast an error from the source to multiple observers', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold(' -1-2-3----4-#'); - const e1subs = ' ^-----------!'; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -1-2-3----4-#'; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----3----4-#'; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ----------4-#'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - multicasted.connect(); - }); - }); - - it('should multicast the same values to multiple observers, but is unsubscribed explicitly and early', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold(' -1-2-3----4-|'); - const e1subs = ' ^--------! '; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const unsub = ' ---------u '; - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----3---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ---------- '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = multicasted.connect(); - }); - }); - - it('should not break unsubscription chains when result is unsubscribed explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const project = (x: string) => of(x); - const subjectFactory = () => new Subject(); - - const e1 = cold(' -1-2-3----4-|'); - const e1subs = ' ^--------! '; - const multicasted = e1.pipe(mergeMap(project), multicast(subjectFactory)) as ConnectableObservable; - const subscriber1 = hot('a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' -1-2-3---- '; - const subscriber2 = hot('----b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' -----3---- '; - const subscriber3 = hot('--------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' ---------- '; - const unsub = ' ---------u '; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - // Set up unsubscription action - let connection: Subscription; - expectObservable( - hot(unsub).pipe( - tap(() => { - connection.unsubscribe(); - }) - ) - ).toBe(unsub); - - connection = multicasted.connect(); - }); - }); - - it('should multicast an empty source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' | '); - const e1subs = ' (^!)'; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const expected = '| '; - - expectObservable(multicasted).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - multicasted.connect(); - }); - }); - - it('should multicast a never source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' -'); - const e1subs = ' ^'; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const expected = '-'; - - expectObservable(multicasted).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - multicasted.connect(); - }); - }); - - it('should multicast a throw source', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' # '); - const e1subs = ' (^!)'; - const multicasted = e1.pipe(multicast(() => new Subject())) as ConnectableObservable; - const expected = '# '; - - expectObservable(multicasted).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - - multicasted.connect(); - }); - }); - - describe('with refCount() and subject factory', () => { - it('should connect when first subscriber subscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' -1-2-3----4-|'); - const e1subs = ' ---^-----------!'; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' ----1-2-3----4-|'; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' --------3----4-|'; - const subscriber3 = hot('-----------c| ').pipe(mergeMapTo(multicasted)); - const expected3 = ' -------------4-|'; - - expectObservable(subscriber1).toBe(expected1); - expectObservable(subscriber2).toBe(expected2); - expectObservable(subscriber3).toBe(expected3); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should disconnect when last subscriber unsubscribes', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' -1-2-3----4-|'); - const e1subs = ' ---^--------! '; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscriber1 = hot('---a| ').pipe(mergeMapTo(multicasted)); - const expected1 = ' ----1-2-3-- '; - const unsub1 = ' ----------! '; - const subscriber2 = hot('-------b| ').pipe(mergeMapTo(multicasted)); - const expected2 = ' --------3---- '; - const unsub2 = ' ------------! '; - - expectObservable(subscriber1, unsub1).toBe(expected1); - expectObservable(subscriber2, unsub2).toBe(expected2); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be retryable when cold source is synchronous', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' (123#) '); - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's '; - const expected1 = ' (123123123123#) '; - const subscribe2 = '-s '; - const expected2 = ' -(123123123123#)'; - const e1subs = [ - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ]; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(3))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(3))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be retryable with ReplaySubject and cold source is synchronous', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new ReplaySubject(1); - - const e1 = cold(' (123#) '); - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's '; - const expected1 = ' (123123123123#) '; - const subscribe2 = '-s '; - const expected2 = ' -(123123123123#)'; - const e1subs = [ - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ]; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(3))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(3))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be repeatable when cold source is synchronous', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' (123|) '); - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's '; - const expected1 = ' (123123123123123|) '; - const subscribe2 = '-s '; - const expected2 = ' -(123123123123123|)'; - const e1subs = [ - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ]; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(5))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(5))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be repeatable with ReplaySubject and cold source is synchronous', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new ReplaySubject(1); - - const e1 = cold(' (123|) '); - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's '; - const expected1 = ' (123123123123123|) '; - const subscribe2 = '-s '; - const expected2 = ' -(123123123123123|)'; - const e1subs = [ - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' (^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ' -(^!) ', - ]; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(5))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(5))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be retryable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' -1-2-3----4-# '); - // -1-2-3----4-# - // -1-2-3----4-# - const e1subs = [ - ' ^-----------! ', - ' ------------^-----------! ', - ' ------------------------^-----------!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's------------------------------------'; - const expected1 = ' -1-2-3----4--1-2-3----4--1-2-3----4-#'; - const subscribe2 = '----s--------------------------------'; - const expected2 = ' -----3----4--1-2-3----4--1-2-3----4-#'; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(2))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(retry(2))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be retryable using a ReplaySubject', () => { - testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new ReplaySubject(1); - - const e1 = cold(' -1-2-3----4-# '); - const e1subs = [ - ' ^-----------! ', - ' ------------^-----------! ', - ' ------------------------^-----------!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const expected1 = ' -1-2-3----4--1-2-3----4--1-2-3----4-#'; - const subscribe2 = time('----| '); - const expected2 = ' ----23----4--1-2-3----4--1-2-3----4-#'; - - expectObservable(multicasted.pipe(retry(2))).toBe(expected1); - - testScheduler.schedule(() => expectObservable(multicasted.pipe(retry(2))).toBe(expected2), subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be repeatable', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new Subject(); - - const e1 = cold(' -1-2-3----4-| '); - const e1subs = [ - ' ^-----------! ', - ' ------------^-----------! ', - ' ------------------------^-----------!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's------------------------------------'; - const expected1 = ' -1-2-3----4--1-2-3----4--1-2-3----4-|'; - const subscribe2 = '----s--------------------------------'; - const expected2 = ' -----3----4--1-2-3----4--1-2-3----4-|'; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(3))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(3))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should be repeatable using a ReplaySubject', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const subjectFactory = () => new ReplaySubject(1); - const e1 = cold(' -1-2-3----4-| '); - const e1subs = [ - ' ^-----------! ', - ' ------------^-----------! ', - ' ------------------------^-----------!', - ]; - const multicasted = e1.pipe(multicast(subjectFactory), refCount()); - const subscribe1 = 's------------------------------------'; - const expected1 = ' -1-2-3----4--1-2-3----4--1-2-3----4-|'; - const subscribe2 = '----s--------------------------------'; - const expected2 = ' ----23----4--1-2-3----4--1-2-3----4-|'; - - expectObservable( - hot(subscribe1).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(3))).toBe(expected1); - }) - ) - ).toBe(subscribe1); - - expectObservable( - hot(subscribe2).pipe( - tap(() => { - expectObservable(multicasted.pipe(repeat(3))).toBe(expected2); - }) - ) - ).toBe(subscribe2); - - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - }); - - it('should multicast one observable to multiple observers', (done) => { - const results1: number[] = []; - const results2: number[] = []; - let subscriptions = 0; - - const source = new Observable((observer) => { - subscriptions++; - observer.next(1); - observer.next(2); - observer.next(3); - observer.next(4); - observer.complete(); - }); - - const connectable = source.pipe( - multicast(() => { - return new Subject(); - }) - ) as ConnectableObservable; - - connectable.subscribe((x) => { - results1.push(x); - }); - - connectable.subscribe((x) => { - results2.push(x); - }); - - expect(results1).to.deep.equal([]); - expect(results2).to.deep.equal([]); - - connectable.connect(); - - expect(results1).to.deep.equal([1, 2, 3, 4]); - expect(results2).to.deep.equal([1, 2, 3, 4]); - expect(subscriptions).to.equal(1); - done(); - }); - - it('should remove all subscribers from the subject when disconnected', () => { - const subject = new Subject(); - const expected = [1, 2, 3, 4]; - let i = 0; - - const source = from([1, 2, 3, 4]).pipe(multicast(subject)) as ConnectableObservable; - - source.subscribe((x) => { - expect(x).to.equal(expected[i++]); - }); - - source.connect(); - expect(subject.observers.length).to.equal(0); - }); - - describe('when given a subject factory', () => { - it('should allow you to reconnect by subscribing again', (done) => { - const expected = [1, 2, 3, 4]; - let i = 0; - - const source = of(1, 2, 3, 4).pipe(multicast(() => new Subject())) as ConnectableObservable; - - source.subscribe({ - next: (x) => { - expect(x).to.equal(expected[i++]); - }, - complete: () => { - i = 0; - - source.subscribe({ - next: (x) => { - expect(x).to.equal(expected[i++]); - }, - complete: done, - }); - - source.connect(); - }, - }); - - source.connect(); - }); - - it('should not throw ObjectUnsubscribedError when used in a switchMap', (done) => { - const source = of(1, 2, 3).pipe( - multicast(() => new Subject()), - refCount() - ); - - const expected = ['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']; - - of('a', 'b', 'c') - .pipe(switchMap((letter) => source.pipe(map((n) => String(letter + n))))) - .subscribe({ - next: (x) => { - expect(x).to.equal(expected.shift()); - }, - error: () => { - done(new Error('should not be called')); - }, - complete: () => { - expect(expected.length).to.equal(0); - done(); - }, - }); - }); - }); - - describe('when given a subject', () => { - it('should not throw ObjectUnsubscribedError when used in a switchMap', (done) => { - const source = of(1, 2, 3).pipe(multicast(new Subject()), refCount()); - - const expected = ['a1', 'a2', 'a3']; - - of('a', 'b', 'c') - .pipe(switchMap((letter) => source.pipe(map((n) => String(letter + n))))) - .subscribe({ - next: (x) => { - expect(x).to.equal(expected.shift()); - }, - error: () => { - done(new Error('should not be called')); - }, - complete: () => { - expect(expected.length).to.equal(0); - done(); - }, - }); - }); - }); -}); diff --git a/spec/operators/repeat-spec.ts b/spec/operators/repeat-spec.ts index 8da78388bb..1333af5a0a 100644 --- a/spec/operators/repeat-spec.ts +++ b/spec/operators/repeat-spec.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { repeat, mergeMap, map, multicast, refCount, take } from 'rxjs/operators'; +import { repeat, mergeMap, map, share, take } from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { of, Subject, Observable, timer } from 'rxjs'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -325,11 +325,7 @@ describe('repeat operator', () => { const expected = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]; of(1, 2, 3) - .pipe( - multicast(() => new Subject()), - refCount(), - repeat(5) - ) + .pipe(share({ connector: () => new Subject() }), repeat(5)) .subscribe({ next: (x: number) => { expect(x).to.equal(expected.shift()); diff --git a/spec/operators/retry-spec.ts b/spec/operators/retry-spec.ts index 3f2d3eb9f2..01b0daa233 100644 --- a/spec/operators/retry-spec.ts +++ b/spec/operators/retry-spec.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { retry, map, take, mergeMap, concatWith, multicast, refCount } from 'rxjs/operators'; +import { retry, map, take, mergeMap, concatWith, share } from 'rxjs/operators'; import { Observable, Observer, defer, range, of, throwError, Subject, timer, EMPTY } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from '../helpers/observableMatcher'; @@ -357,12 +357,7 @@ describe('retry', () => { const expected = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]; of(1, 2, 3) - .pipe( - concatWith(throwError(() => 'bad!')), - multicast(() => new Subject()), - refCount(), - retry(4) - ) + .pipe(concatWith(throwError(() => 'bad!')), share({ connector: () => new Subject() }), retry(4)) .subscribe({ next(x: number) { expect(x).to.equal(expected.shift()); diff --git a/src/index.ts b/src/index.ts index 17010f2d01..17df30dc49 100644 --- a/src/index.ts +++ b/src/index.ts @@ -145,7 +145,6 @@ export { mergeMapTo } from './internal/operators/mergeMapTo'; export { mergeScan } from './internal/operators/mergeScan'; export { mergeWith } from './internal/operators/mergeWith'; export { min } from './internal/operators/min'; -export { multicast } from './internal/operators/multicast'; export { observeOn } from './internal/operators/observeOn'; export { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWith'; export { pairwise } from './internal/operators/pairwise'; diff --git a/src/internal/operators/multicast.ts b/src/internal/operators/multicast.ts deleted file mode 100644 index 4ea03d2f43..0000000000 --- a/src/internal/operators/multicast.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { Subject } from '../Subject'; -import { Observable } from '../Observable'; -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { OperatorFunction, UnaryFunction, ObservedValueOf, ObservableInput } from '../types'; -import { isFunction } from '../util/isFunction'; -import { connect } from './connect'; - -/** - * An operator that creates a {@link ConnectableObservable}, that when connected, - * with the `connect` method, will use the provided subject to multicast the values - * from the source to all consumers. - * - * @param subject The subject to multicast through. - * @return A function that returns a {@link ConnectableObservable} - * @deprecated Will be removed in v8. To create a connectable observable, use {@link connectable}. - * If you're using {@link refCount} after `multicast`, use the {@link share} operator instead. - * `multicast(subject), refCount()` is equivalent to - * `share({ connector: () => subject, resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function multicast(subject: Subject): UnaryFunction, ConnectableObservable>; - -/** - * Because this is deprecated in favor of the {@link connect} operator, and was otherwise poorly documented, - * rather than duplicate the effort of documenting the same behavior, please see documentation for the - * {@link connect} operator. - * - * @param subject The subject used to multicast. - * @param selector A setup function to setup the multicast - * @return A function that returns an observable that mirrors the observable returned by the selector. - * @deprecated Will be removed in v8. Use the {@link connect} operator instead. - * `multicast(subject, selector)` is equivalent to - * `connect(selector, { connector: () => subject })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function multicast>( - subject: Subject, - selector: (shared: Observable) => O -): OperatorFunction>; - -/** - * An operator that creates a {@link ConnectableObservable}, that when connected, - * with the `connect` method, will use the provided subject to multicast the values - * from the source to all consumers. - * - * @param subjectFactory A factory that will be called to create the subject. Passing a function here - * will cause the underlying subject to be "reset" on error, completion, or refCounted unsubscription of - * the source. - * @return A function that returns a {@link ConnectableObservable} - * @deprecated Will be removed in v8. To create a connectable observable, use {@link connectable}. - * If you're using {@link refCount} after `multicast`, use the {@link share} operator instead. - * `multicast(() => new BehaviorSubject('test')), refCount()` is equivalent to - * `share({ connector: () => new BehaviorSubject('test') })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function multicast(subjectFactory: () => Subject): UnaryFunction, ConnectableObservable>; - -/** - * Because this is deprecated in favor of the {@link connect} operator, and was otherwise poorly documented, - * rather than duplicate the effort of documenting the same behavior, please see documentation for the - * {@link connect} operator. - * - * @param subjectFactory A factory that creates the subject used to multicast. - * @param selector A function to setup the multicast and select the output. - * @return A function that returns an observable that mirrors the observable returned by the selector. - * @deprecated Will be removed in v8. Use the {@link connect} operator instead. - * `multicast(subjectFactory, selector)` is equivalent to - * `connect(selector, { connector: subjectFactory })`. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function multicast>( - subjectFactory: () => Subject, - selector: (shared: Observable) => O -): OperatorFunction>; - -/** - * @deprecated Will be removed in v8. Use the {@link connectable} observable, the {@link connect} operator or the - * {@link share} operator instead. See the overloads below for equivalent replacement examples of this operator's - * behaviors. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function multicast( - subjectOrSubjectFactory: Subject | (() => Subject), - selector?: (source: Observable) => Observable -): OperatorFunction { - const subjectFactory = isFunction(subjectOrSubjectFactory) ? subjectOrSubjectFactory : () => subjectOrSubjectFactory; - - if (isFunction(selector)) { - // If a selector function is provided, then we're a "normal" operator that isn't - // going to return a ConnectableObservable. We can use `connect` to do what we - // need to do. - return connect(selector, { - connector: subjectFactory, - }); - } - - return (source: Observable) => new ConnectableObservable(source, subjectFactory); -} diff --git a/src/operators/index.ts b/src/operators/index.ts index 60932a1f45..c5ed842698 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -49,7 +49,6 @@ export { mergeMapTo } from '../internal/operators/mergeMapTo'; export { mergeScan } from '../internal/operators/mergeScan'; export { mergeWith } from '../internal/operators/mergeWith'; export { min } from '../internal/operators/min'; -export { multicast } from '../internal/operators/multicast'; export { observeOn } from '../internal/operators/observeOn'; export { onErrorResumeNextWith } from '../internal/operators/onErrorResumeNextWith'; export { pairwise } from '../internal/operators/pairwise'; From af5e91263db191a79feee109eee7855ca923048b Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:45:59 +0200 Subject: [PATCH 08/15] feat(operator): removed deprecated `refCount` operator BREAKING CHANGE: The `refCount` operator is no longer available. [Multicasting](https://rxjs.dev/deprecations/multicasting#refcount). BREAKING CHANGE: The `ConnectableObservable` observable is no longer available. [Multicasting](https://rxjs.dev/deprecations/multicasting#connectableobservable). --- .../images/marble-diagrams/refCount.png | Bin 45474 -> 0 bytes spec-dtslint/operators/refCount-spec.ts | 10 -- spec/Observable-spec.ts | 2 +- spec/index-spec.ts | 2 - spec/operators/index-spec.ts | 1 - src/index.ts | 2 - .../observable/ConnectableObservable.ts | 104 --------------- src/internal/operators/refCount.ts | 119 ------------------ src/internal/operators/share.ts | 1 - src/operators/index.ts | 1 - 10 files changed, 1 insertion(+), 241 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/refCount.png delete mode 100644 spec-dtslint/operators/refCount-spec.ts delete mode 100644 src/internal/observable/ConnectableObservable.ts delete mode 100644 src/internal/operators/refCount.ts diff --git a/docs_app/src/assets/images/marble-diagrams/refCount.png b/docs_app/src/assets/images/marble-diagrams/refCount.png deleted file mode 100644 index 57b0328a10d586a2f375edf1483605add6c2c92b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45474 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 { - const a = of(1, 2, 3).pipe(refCount()); // $ExpectType Observable -}); - -it('should not accept any parameters', () => { - const a = of(1, 2, 3).pipe(refCount(1)); // $ExpectError -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index f1b09324d5..2885ac72ff 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, refCount, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; +import { map, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; diff --git a/spec/index-spec.ts b/spec/index-spec.ts index d73bcf6125..e8425aea79 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -5,7 +5,6 @@ import { expect } from 'chai'; describe('index', () => { it('should export Observable', () => { expect(index.Observable).to.exist; - expect(index.ConnectableObservable).to.exist; // Interfaces can be checked by creating a variable of that type let operator: index.Operator; }); @@ -135,7 +134,6 @@ describe('index', () => { expect(index.repeatWhen).to.exist; expect(index.retry).to.exist; expect(index.retryWhen).to.exist; - expect(index.refCount).to.exist; expect(index.sample).to.exist; expect(index.sampleTime).to.exist; expect(index.scan).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index 25143646fb..eb92edd1df 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -58,7 +58,6 @@ describe('operators/index', () => { expect(index.repeatWhen).to.exist; expect(index.retry).to.exist; expect(index.retryWhen).to.exist; - expect(index.refCount).to.exist; expect(index.sample).to.exist; expect(index.sampleTime).to.exist; expect(index.scan).to.exist; diff --git a/src/index.ts b/src/index.ts index 17df30dc49..0e75cb5323 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,6 @@ /* Observable */ export { Observable } from './internal/Observable'; -export { ConnectableObservable } from './internal/observable/ConnectableObservable'; export { GroupedObservable } from './internal/operators/groupBy'; export { Operator } from './internal/Operator'; export { observable } from './internal/symbol/observable'; @@ -155,7 +154,6 @@ export { repeat, RepeatConfig } from './internal/operators/repeat'; export { repeatWhen } from './internal/operators/repeatWhen'; export { retry, RetryConfig } from './internal/operators/retry'; export { retryWhen } from './internal/operators/retryWhen'; -export { refCount } from './internal/operators/refCount'; export { sample } from './internal/operators/sample'; export { sampleTime } from './internal/operators/sampleTime'; export { scan } from './internal/operators/scan'; diff --git a/src/internal/observable/ConnectableObservable.ts b/src/internal/observable/ConnectableObservable.ts deleted file mode 100644 index bd1c76fbe1..0000000000 --- a/src/internal/observable/ConnectableObservable.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Subject } from '../Subject'; -import { Observable } from '../Observable'; -import { Subscriber } from '../Subscriber'; -import { Subscription } from '../Subscription'; -import { refCount as higherOrderRefCount } from '../operators/refCount'; -import { createOperatorSubscriber } from '../operators/OperatorSubscriber'; -import { hasLift } from '../util/lift'; - -/** - * @class ConnectableObservable - * @deprecated Will be removed in v8. Use {@link connectable} to create a connectable observable. - * If you are using the `refCount` method of `ConnectableObservable`, use the {@link share} operator - * instead. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export class ConnectableObservable extends Observable { - protected _subject: Subject | null = null; - protected _refCount: number = 0; - protected _connection: Subscription | null = null; - - /** - * @param source The source observable - * @param subjectFactory The factory that creates the subject used internally. - * @deprecated Will be removed in v8. Use {@link connectable} to create a connectable observable. - * `new ConnectableObservable(source, factory)` is equivalent to - * `connectable(source, { connector: factory })`. - * When the `refCount()` method is needed, the {@link share} operator should be used instead: - * `new ConnectableObservable(source, factory).refCount()` is equivalent to - * `source.pipe(share({ connector: factory }))`. - * Details: https://rxjs.dev/deprecations/multicasting - */ - constructor(public source: Observable, protected subjectFactory: () => Subject) { - super(); - // If we have lift, monkey patch that here. This is done so custom observable - // types will compose through multicast. Otherwise the resulting observable would - // simply be an instance of `ConnectableObservable`. - if (hasLift(source)) { - this.lift = source.lift; - } - } - - /** @internal */ - protected _subscribe(subscriber: Subscriber) { - return this.getSubject().subscribe(subscriber); - } - - protected getSubject(): Subject { - const subject = this._subject; - if (!subject || subject.isStopped) { - this._subject = this.subjectFactory(); - } - return this._subject!; - } - - protected _teardown() { - this._refCount = 0; - const { _connection } = this; - this._subject = this._connection = null; - _connection?.unsubscribe(); - } - - /** - * @deprecated {@link ConnectableObservable} will be removed in v8. Use {@link connectable} instead. - * Details: https://rxjs.dev/deprecations/multicasting - */ - connect(): Subscription { - let connection = this._connection; - if (!connection) { - connection = this._connection = new Subscription(); - const subject = this.getSubject(); - connection.add( - this.source.subscribe( - createOperatorSubscriber( - subject as any, - undefined, - () => { - this._teardown(); - subject.complete(); - }, - (err) => { - this._teardown(); - subject.error(err); - }, - () => this._teardown() - ) - ) - ); - - if (connection.closed) { - this._connection = null; - connection = Subscription.EMPTY; - } - } - return connection; - } - - /** - * @deprecated {@link ConnectableObservable} will be removed in v8. Use the {@link share} operator instead. - * Details: https://rxjs.dev/deprecations/multicasting - */ - refCount(): Observable { - return higherOrderRefCount()(this) as Observable; - } -} diff --git a/src/internal/operators/refCount.ts b/src/internal/operators/refCount.ts deleted file mode 100644 index c4162c0d70..0000000000 --- a/src/internal/operators/refCount.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { Subscription } from '../Subscription'; -import { MonoTypeOperatorFunction } from '../types'; -import { operate } from '../util/lift'; -import { createOperatorSubscriber } from './OperatorSubscriber'; - -/** - * Make a {@link ConnectableObservable} behave like a ordinary observable and automates the way - * you can connect to it. - * - * Internally it counts the subscriptions to the observable and subscribes (only once) to the source if - * the number of subscriptions is larger than 0. If the number of subscriptions is smaller than 1, it - * unsubscribes from the source. This way you can make sure that everything before the *published* - * refCount has only a single subscription independently of the number of subscribers to the target - * observable. - * - * Note that using the {@link share} operator is exactly the same as using the `multicast(() => new Subject())` operator - * (making the observable hot) and the *refCount* operator in a sequence. - * - * ![](refCount.png) - * - * ## Example - * - * In the following example there are two intervals turned into connectable observables - * by using the *publish* operator. The first one uses the *refCount* operator, the - * second one does not use it. You will notice that a connectable observable does nothing - * until you call its connect function. - * - * ```ts - * import { interval, tap, publish, refCount } from 'rxjs'; - * - * // Turn the interval observable into a ConnectableObservable (hot) - * const refCountInterval = interval(400).pipe( - * tap(num => console.log(`refCount ${ num }`)), - * publish(), - * refCount() - * ); - * - * const publishedInterval = interval(400).pipe( - * tap(num => console.log(`publish ${ num }`)), - * publish() - * ); - * - * refCountInterval.subscribe(); - * refCountInterval.subscribe(); - * // 'refCount 0' -----> 'refCount 1' -----> etc - * // All subscriptions will receive the same value and the tap (and - * // every other operator) before the `publish` operator will be executed - * // only once per event independently of the number of subscriptions. - * - * publishedInterval.subscribe(); - * // Nothing happens until you call .connect() on the observable. - * ``` - * - * @return A function that returns an Observable that automates the connection - * to ConnectableObservable. - * @see {@link ConnectableObservable} - * @see {@link share} - * @see {@link publish} - * @deprecated Replaced with the {@link share} operator. How `share` is used - * will depend on the connectable observable you created just prior to the - * `refCount` operator. - * Details: https://rxjs.dev/deprecations/multicasting - */ -export function refCount(): MonoTypeOperatorFunction { - return operate((source, subscriber) => { - let connection: Subscription | null = null; - - (source as any)._refCount++; - - const refCounter = createOperatorSubscriber(subscriber, undefined, undefined, undefined, () => { - if (!source || (source as any)._refCount <= 0 || 0 < --(source as any)._refCount) { - connection = null; - return; - } - - /// - // Compare the local RefCountSubscriber's connection Subscription to the - // connection Subscription on the shared ConnectableObservable. In cases - // where the ConnectableObservable source synchronously emits values, and - // the RefCountSubscriber's downstream Observers synchronously unsubscribe, - // execution continues to here before the RefCountOperator has a chance to - // supply the RefCountSubscriber with the shared connection Subscription. - // For example: - // ``` - // range(0, 10).pipe( - // publish(), - // refCount(), - // take(5), - // ) - // .subscribe(); - // ``` - // In order to account for this case, RefCountSubscriber should only dispose - // the ConnectableObservable's shared connection Subscription if the - // connection Subscription exists, *and* either: - // a. RefCountSubscriber doesn't have a reference to the shared connection - // Subscription yet, or, - // b. RefCountSubscriber's connection Subscription reference is identical - // to the shared connection Subscription - /// - - const sharedConnection = (source as any)._connection; - const conn = connection; - connection = null; - - if (sharedConnection && (!conn || sharedConnection === conn)) { - sharedConnection.unsubscribe(); - } - - subscriber.unsubscribe(); - }); - - source.subscribe(refCounter); - - if (!refCounter.closed) { - connection = (source as ConnectableObservable).connect(); - } - }); -} diff --git a/src/internal/operators/share.ts b/src/internal/operators/share.ts index 23b6d62a99..429504c383 100644 --- a/src/internal/operators/share.ts +++ b/src/internal/operators/share.ts @@ -53,7 +53,6 @@ export function share(options: ShareConfig): MonoTypeOperatorFunction; * Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one * Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will * unsubscribe from the source Observable. Because the Observable is multicasting it makes the stream `hot`. - * This is an alias for `multicast(() => new Subject()), refCount()`. * * The subscription to the underlying source Observable can be reset (unsubscribe and resubscribe for new subscribers), * if the subscriber count to the shared observable drops to 0, or if the source Observable errors or completes. It is diff --git a/src/operators/index.ts b/src/operators/index.ts index c5ed842698..cef3c25346 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -61,7 +61,6 @@ export { repeat, RepeatConfig } from '../internal/operators/repeat'; export { repeatWhen } from '../internal/operators/repeatWhen'; export { retry, RetryConfig } from '../internal/operators/retry'; export { retryWhen } from '../internal/operators/retryWhen'; -export { refCount } from '../internal/operators/refCount'; export { sample } from '../internal/operators/sample'; export { sampleTime } from '../internal/operators/sampleTime'; export { scan } from '../internal/operators/scan'; From 78b1cf22137a3441ecf626801a8d30ae41d91f90 Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:48:42 +0200 Subject: [PATCH 09/15] feat(operator): removed deprecated `race` operator BREAKING CHANGE: The `race` operator is no longer available. Use `raceWith`. --- spec-dtslint/operators/race-spec.ts | 20 --- spec/Observable-spec.ts | 6 +- spec/operators/race-legacy-spec.ts | 265 ---------------------------- src/internal/operators/race.ts | 20 --- src/operators/index.ts | 1 - 5 files changed, 3 insertions(+), 309 deletions(-) delete mode 100644 spec-dtslint/operators/race-spec.ts delete mode 100644 spec/operators/race-legacy-spec.ts delete mode 100644 src/internal/operators/race.ts diff --git a/spec-dtslint/operators/race-spec.ts b/spec-dtslint/operators/race-spec.ts deleted file mode 100644 index dc18fd0973..0000000000 --- a/spec-dtslint/operators/race-spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { of } from 'rxjs'; -import { race } from 'rxjs/operators'; - -it('should infer correctly', () => { - const o = of('a', 'b', 'c').pipe(race()); // $ExpectType Observable -}); - -it('should allow observables', () => { - const o = of('a', 'b', 'c').pipe(race(of('x', 'y', 'z'))); // $ExpectType Observable - const p = of('a', 'b', 'c').pipe(race(of('x', 'y', 'z'), of('t', 'i', 'm'))); // $ExpectType Observable -}); - -it('should allow an array of observables', () => { - const o = of('a', 'b', 'c').pipe(race([of('x', 'y', 'z')])); // $ExpectType Observable - const p = of('a', 'b', 'c').pipe(race([of('x', 'y', 'z'), of('t', 'i', 'm')])); // $ExpectType Observable -}); - -it('should be possible to use nested arrays', () => { - const o = of('a', 'b', 'c').pipe(race([of('x', 'y', 'z')])); // $ExpectType Observable -}); diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index 2885ac72ff..7f70d62dda 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { TeardownLogic } from '../src/internal/types'; import { Observable, config, Subscription, Subscriber, Operator, NEVER, Subject, of, throwError, EMPTY } from 'rxjs'; -import { map, filter, count, tap, combineLatestWith, concatWith, mergeWith, race, zipWith, catchError, share} from 'rxjs/operators'; +import { map, filter, count, tap, combineLatestWith, concatWith, mergeWith, raceWith, zipWith, catchError, share} from 'rxjs/operators'; import { TestScheduler } from 'rxjs/testing'; import { observableMatcher } from './helpers/observableMatcher'; @@ -867,7 +867,7 @@ describe('Observable.lift', () => { }); }); - it('should compose through race', () => { + it('should compose through raceWith', () => { rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { const e1 = cold(' ---a-----b-----c----|'); const e1subs = ' ^-------------------!'; @@ -876,7 +876,7 @@ describe('Observable.lift', () => { const expected = '---a-----b-----c----|'; const result = MyCustomObservable.from(e1).pipe( - race(e2) + raceWith(e2) ); expect(result instanceof MyCustomObservable).to.be.true; diff --git a/spec/operators/race-legacy-spec.ts b/spec/operators/race-legacy-spec.ts deleted file mode 100644 index 9c9d9241d7..0000000000 --- a/spec/operators/race-legacy-spec.ts +++ /dev/null @@ -1,265 +0,0 @@ -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { EMPTY, NEVER, of, timer, defer, Observable, throwError } from 'rxjs'; -import { race, mergeMap, map, finalize, startWith } from 'rxjs/operators'; -import { TestScheduler } from 'rxjs/testing'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {race} */ -describe('race operator', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should race cold and cold', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---a-----b-----c----| '); - const e1subs = ' ^-------------------! '; - const e2 = cold(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----b-----c----| '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should race cold and cold and accept an Array of Observable argument', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---a-----b-----c----| '); - const e1subs = ' ^-------------------! '; - const e2 = cold(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----b-----c----| '; - - const result = e1.pipe(race([e2])); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should race hot and hot', () => { - testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' ---a-----b-----c----| '); - const e1subs = ' ^-------------------! '; - const e2 = hot(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----b-----c----| '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should race hot and cold', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---a-----b-----c----| '); - const e1subs = ' ^-------------------! '; - const e2 = hot(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----b-----c----| '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should race 2nd and 1st', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ------x-----y-----z----|'); - const e1subs = ' ^--! '; - const e2 = cold(' ---a-----b-----c----| '); - const e2subs = ' ^-------------------! '; - const expected = '---a-----b-----c----| '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should race emit and complete', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold(' -----| '); - const e1subs = ' ^----! '; - const e2 = hot(' ------x-----y-----z----|'); - const e2subs = ' ^----! '; - const expected = '-----| '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should allow unsubscribing early and explicitly', () => { - testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = cold('---a-----b-----c----| '); - const e1subs = ' ^-----------! '; - const e2 = hot(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----b--- '; - const unsub = ' ------------! '; - - const result = e1.pipe(race(e2)); - - expectObservable(result, unsub).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should not break unsubscription chains when unsubscribed explicitly', () => { - testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' --a--^--b--c---d-| '); - const e1subs = ' ^--------! '; - const e2 = hot(' ---e-^---f--g---h-|'); - const e2subs = ' ^--! '; - const expected = ' ---b--c--- '; - const unsub = ' ---------! '; - - const result = e1.pipe( - mergeMap((x: string) => of(x)), - race(e2), - mergeMap((x: string) => of(x)) - ); - - expectObservable(result, unsub).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should never emit when given non emitting sources', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---|'); - const e2 = cold(' ---|'); - const e1subs = ' ^--!'; - const expected = '---|'; - - const source = e1.pipe(race(e2)); - - expectObservable(source).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should throw when error occurs mid stream', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---a-----# '); - const e1subs = ' ^--------! '; - const e2 = cold(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---a-----# '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should throw when error occurs before a winner is found', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' ---# '); - const e1subs = ' ^--! '; - const e2 = cold(' ------x-----y-----z----|'); - const e2subs = ' ^--! '; - const expected = '---# '; - - const result = e1.pipe(race(e2)); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - expectSubscriptions(e2.subscriptions).toBe(e2subs); - }); - }); - - it('should allow observable emits immediately', (done) => { - const e1 = of(true); - const e2 = timer(200).pipe(map((_) => false)); - - e1.pipe(race(e2)).subscribe({ - next: (x) => { - expect(x).to.be.true; - }, - error: done, - complete: done, - }); - }); - - it('should ignore latter observables if a former one emits immediately', () => { - const onNext = sinon.spy(); - const onSubscribe = sinon.spy() as any; - const e1 = of('a'); // Wins the race - const e2 = defer(onSubscribe); // Should be ignored - - e1.pipe(race(e2)).subscribe(onNext); - expect(onNext.calledWithExactly('a')).to.be.true; - expect(onSubscribe.called).to.be.false; - }); - - it('should ignore latter observables if a former one completes immediately', () => { - const onComplete = sinon.spy(); - const onSubscribe = sinon.spy() as any; - const e1 = EMPTY; // Wins the race - const e2 = defer(onSubscribe); // Should be ignored - - e1.pipe(race(e2)).subscribe({ complete: onComplete }); - expect(onComplete.calledWithExactly()).to.be.true; - expect(onSubscribe.called).to.be.false; - }); - - it('should ignore latter observables if a former one errors immediately', () => { - const onError = sinon.spy(); - const onSubscribe = sinon.spy() as any; - const e1 = throwError(() => 'kaboom'); // Wins the race - const e2 = defer(onSubscribe); // Should be ignored - - e1.pipe(race(e2)).subscribe({ error: onError }); - expect(onError.calledWithExactly('kaboom')).to.be.true; - expect(onSubscribe.called).to.be.false; - }); - - it('should unsubscribe former observables if a latter one emits immediately', () => { - const onNext = sinon.spy(); - const onUnsubscribe = sinon.spy(); - const e1 = NEVER.pipe(finalize(onUnsubscribe)); // Should be unsubscribed - const e2 = of('b'); // Wins the race - - e1.pipe(race(e2)).subscribe(onNext); - expect(onNext.calledWithExactly('b')).to.be.true; - expect(onUnsubscribe.calledOnce).to.be.true; - }); - - it('should unsubscribe from immediately emitting observable on unsubscription', () => { - const onNext = sinon.spy(); - const onUnsubscribe = sinon.spy(); - const e1 = >NEVER.pipe(startWith('a'), finalize(onUnsubscribe)); // Wins the race - const e2 = NEVER; // Loses the race - - const subscription = e1.pipe(race(e2)).subscribe(onNext); - expect(onNext.calledWithExactly('a')).to.be.true; - expect(onUnsubscribe.called).to.be.false; - subscription.unsubscribe(); - expect(onUnsubscribe.calledOnce).to.be.true; - }); -}); diff --git a/src/internal/operators/race.ts b/src/internal/operators/race.ts deleted file mode 100644 index efa8cd94cb..0000000000 --- a/src/internal/operators/race.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ObservableInputTuple, OperatorFunction } from '../types'; -import { argsOrArgArray } from '../util/argsOrArgArray'; -import { raceWith } from './raceWith'; - -/** @deprecated Replaced with {@link raceWith}. Will be removed in v8. */ -export function race(otherSources: [...ObservableInputTuple]): OperatorFunction; -/** @deprecated Replaced with {@link raceWith}. Will be removed in v8. */ -export function race(...otherSources: [...ObservableInputTuple]): OperatorFunction; - -/** - * Returns an Observable that mirrors the first source Observable to emit a next, - * error or complete notification from the combination of this Observable and supplied Observables. - * @param args Sources used to race for which Observable emits first. - * @return A function that returns an Observable that mirrors the output of the - * first Observable to emit an item. - * @deprecated Replaced with {@link raceWith}. Will be removed in v8. - */ -export function race(...args: any[]): OperatorFunction { - return raceWith(...argsOrArgArray(args)); -} diff --git a/src/operators/index.ts b/src/operators/index.ts index cef3c25346..7392d29aea 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -54,7 +54,6 @@ export { onErrorResumeNextWith } from '../internal/operators/onErrorResumeNextWi export { pairwise } from '../internal/operators/pairwise'; export { partition } from '../internal/operators/partition'; export { pluck } from '../internal/operators/pluck'; -export { race } from '../internal/operators/race'; export { raceWith } from '../internal/operators/raceWith'; export { reduce } from '../internal/operators/reduce'; export { repeat, RepeatConfig } from '../internal/operators/repeat'; From 39ad76acc39c6d8550ee1129009eae0db6b3e13c Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 01:54:18 +0200 Subject: [PATCH 10/15] feat(operator): removed deprecated `pluck` operator BREAKING CHANGE: The `pluck('foo', 'bar')` operator is no longer available. Use `map(x => x?.foo?.bar)`. --- docs_app/content/guide/operators.md | 1 - docs_app/content/guide/overview.md | 2 +- .../assets/images/marble-diagrams/pluck.png | Bin 46229 -> 0 bytes .../src/lib/interfaces.ts | 1 - .../decision-tree-generator/src/tree.yml | 2 +- spec-dtslint/operators/pluck-spec.ts | 71 ----- spec/index-spec.ts | 1 - spec/operators/index-spec.ts | 1 - spec/operators/pluck-spec.ts | 272 ------------------ src/index.ts | 1 - src/internal/operators/map.ts | 1 - src/internal/operators/pluck.ts | 106 ------- src/operators/index.ts | 1 - 13 files changed, 2 insertions(+), 458 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/pluck.png delete mode 100644 spec-dtslint/operators/pluck-spec.ts delete mode 100644 spec/operators/pluck-spec.ts delete mode 100644 src/internal/operators/pluck.ts diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index cd53cbde03..404bf19bee 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -162,7 +162,6 @@ These are Observable creation operators that also have join functionality -- emi - [`mergeScan`](/api/operators/mergeScan) - [`pairwise`](/api/operators/pairwise) - [`partition`](/api/operators/partition) -- [`pluck`](/api/operators/pluck) - [`scan`](/api/operators/scan) - [`switchScan`](/api/operators/switchScan) - [`switchMap`](/api/operators/switchMap) diff --git a/docs_app/content/guide/overview.md b/docs_app/content/guide/overview.md index 23dc95a2cf..7d1ad96f9e 100644 --- a/docs_app/content/guide/overview.md +++ b/docs_app/content/guide/overview.md @@ -121,4 +121,4 @@ fromEvent(document, 'click') .subscribe((count) => console.log(count)); ``` -Other value producing operators are [**pluck**](../api/operators/pluck), [**pairwise**](../api/operators/pairwise), [**sample**](../api/operators/sample) etc. +Other value producing operators are [**pairwise**](../api/operators/pairwise), [**sample**](../api/operators/sample) etc. diff --git a/docs_app/src/assets/images/marble-diagrams/pluck.png b/docs_app/src/assets/images/marble-diagrams/pluck.png deleted file mode 100644 index 9ddfcbe5ea29ed359fa087b9275f41cfb19bfbf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46229 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 Wf4)I0O~eKIEsai@>EljZi2XB0J54_T diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index b727940caf..d30efa18e6 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -64,7 +64,6 @@ export type ApiUnion = | 'pairwise' | 'partition' | 'pipe' - | 'pluck' | 'race' | 'range' | 'reduce' diff --git a/docs_app/tools/decision-tree-generator/src/tree.yml b/docs_app/tools/decision-tree-generator/src/tree.yml index 10805e02fc..b0cdd43298 100644 --- a/docs_app/tools/decision-tree-generator/src/tree.yml +++ b/docs_app/tools/decision-tree-generator/src/tree.yml @@ -10,7 +10,7 @@ - label: map - label: I want to pick a property off each emitted value children: - - label: pluck + - label: map - label: I want to spy the values being emitted without affecting them children: - label: tap diff --git a/spec-dtslint/operators/pluck-spec.ts b/spec-dtslint/operators/pluck-spec.ts deleted file mode 100644 index 1fef47f5ce..0000000000 --- a/spec-dtslint/operators/pluck-spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { of, Observable } from 'rxjs'; -import { pluck } from 'rxjs/operators'; - -it('should infer correctly', () => { - const a = of({ name: 'abc' }).pipe(pluck('name')); // $ExpectType Observable -}); - -it('should support nested object of 2 layer depth', () => { - const a = of({ a: { name: 'abc' } }).pipe(pluck('a', 'name')); // $ExpectType Observable -}); - -it('should support nested object of 3 layer depth', () => { - const a = of({ a: { b: { name: 'abc' } } }).pipe(pluck('a', 'b', 'name')); // $ExpectType Observable -}); - -it('should support nested object of 4 layer depth', () => { - const a = of({ a: { b: { c: { name: 'abc' } } } }).pipe(pluck('a', 'b', 'c', 'name')); // $ExpectType Observable -}); - -it('should support nested object of 5 layer depth', () => { - const a = of({ a: { b: { c: { d: { name: 'abc' } } } } }).pipe(pluck('a', 'b', 'c', 'd', 'name')); // $ExpectType Observable -}); - -it('should support nested object of 6 layer depth', () => { - const a = of({ a: { b: { c: { d: { e: { name: 'abc' } } } } } }).pipe(pluck('a', 'b', 'c', 'd', 'e', 'name')); // $ExpectType Observable -}); - -it('should support nested object of more than 6 layer depth', () => { - const a = of({ a: { b: { c: { d: { e: { f: { name: 'abc' } } } } } } }).pipe(pluck('a', 'b', 'c', 'd', 'e', 'f', 'name')); // $ExpectType Observable -}); - -it('should accept existing keys only', () => { - const a = of({ name: 'abc' }).pipe(pluck('xyz')); // $ExpectType Observable -}); - -it('should not accept empty parameter', () => { - const a = of({ name: 'abc' }).pipe(pluck()); // $ExpectType Observable -}); - -it('should not accept a number when plucking an object', () => { - const a = of({ name: 'abc' }).pipe(pluck(1)); // $ExpectError -}); - -it('should not infer type from the variable if key doesn\'t exist', () => { - const a: Observable = of({ name: 'abc' }).pipe(pluck('xyz')); // $ExpectError -}); - -it('should accept a spread of arguments', () => { - const obj = { - foo: { - bar: { - baz: 123 - } - } - }; - - const path = ['foo', 'bar', 'baz']; - const a = of(obj).pipe(pluck(...path)); // $ExpectType Observable - - const path2 = ['bar', 'baz']; - const b = of(obj).pipe(pluck('foo', ...path2)); // $ExpectType Observable -}); - -it('should support arrays', () => { - const a = of(['abc']).pipe(pluck(0)) // $ExpectType Observable -}) - -it('should support picking by symbols', () => { - const sym = Symbol('sym') - const a = of({ [sym]: 'abc' }).pipe(pluck(sym)) // $ExpectType Observable -}) diff --git a/spec/index-spec.ts b/spec/index-spec.ts index e8425aea79..53d56a4a83 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -127,7 +127,6 @@ describe('index', () => { expect(index.min).to.exist; expect(index.observeOn).to.exist; expect(index.pairwise).to.exist; - expect(index.pluck).to.exist; expect(index.raceWith).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; diff --git a/spec/operators/index-spec.ts b/spec/operators/index-spec.ts index eb92edd1df..eae792519d 100644 --- a/spec/operators/index-spec.ts +++ b/spec/operators/index-spec.ts @@ -52,7 +52,6 @@ describe('operators/index', () => { expect(index.observeOn).to.exist; expect(index.pairwise).to.exist; expect(index.partition).to.exist; - expect(index.pluck).to.exist; expect(index.reduce).to.exist; expect(index.repeat).to.exist; expect(index.repeatWhen).to.exist; diff --git a/spec/operators/pluck-spec.ts b/spec/operators/pluck-spec.ts deleted file mode 100644 index fe2146dfe7..0000000000 --- a/spec/operators/pluck-spec.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { expect } from 'chai'; -import { TestScheduler } from 'rxjs/internal/testing/TestScheduler'; -import { pluck, map, mergeMap, take } from 'rxjs/operators'; -import { of, Observable } from 'rxjs'; -import { observableMatcher } from '../helpers/observableMatcher'; - -/** @test {pluck} */ -describe('pluck', () => { - let testScheduler: TestScheduler; - - beforeEach(() => { - testScheduler = new TestScheduler(observableMatcher); - }); - - it('should dematerialize an Observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { - a: '{v:1}', - b: '{v:2}', - c: '{v:3}', - }; - - const e1 = cold(' --a--b--c--|', inputs); - const e1subs = ' ^----------!'; - const expected = '--x--y--z--|'; - - const result = e1.pipe( - map((x) => ({ v: x.charAt(3) })), - pluck('v') - ); - - expectObservable(result).toBe(expected, { x: '1', y: '2', z: '3' }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should work for one array', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { x: ['abc'] }; - const e1 = cold(' --x--|', inputs); - const e1subs = ' ^----!'; - const expected = '--y--|'; - - const result = e1.pipe(pluck(0)); - - expectObservable(result).toBe(expected, { y: 'abc' }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should work for one object', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { x: { prop: 42 } }; - const e1 = cold(' --x--|', inputs); - const e1subs = ' ^----!'; - const expected = '--y--|'; - - const result = e1.pipe(pluck('prop')); - - expectObservable(result).toBe(expected, { y: 42 }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should work for multiple objects', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { - a: { prop: '1' }, - b: { prop: '2' }, - c: { prop: '3' }, - d: { prop: '4' }, - e: { prop: '5' }, - }; - const e1 = cold(' --a-b--c-d---e-|', inputs); - const e1subs = ' ^--------------!'; - const expected = '--1-2--3-4---5-|'; - - const result = e1.pipe(pluck('prop')); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should work with deep nested properties', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { - a: { a: { b: { c: '1' } } }, - b: { a: { b: { c: '2' } } }, - c: { a: { b: { c: '3' } } }, - d: { a: { b: { c: '4' } } }, - e: { a: { b: { c: '5' } } }, - }; - const e1 = cold(' --a-b--c-d---e-|', inputs); - const e1subs = ' ^--------------!'; - const expected = '--1-2--3-4---5-|'; - - const result = e1.pipe(pluck('a', 'b', 'c')); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should work with edge cases of deep nested properties', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { - a: { i: { j: { k: 1 } } }, - b: { i: { j: 2 } }, - c: { i: { k: { k: 3 } } }, - d: {}, - e: { i: { j: { k: 5 } } }, - }; - const e1 = cold(' --a-b--c-d---e-|', inputs); - const e1subs = ' ^--------------!'; - const expected = '--v-w--x-y---z-|'; - const values: { [key: string]: number | undefined } = { v: 1, w: undefined, x: undefined, y: undefined, z: 5 }; - - const result = e1.pipe(pluck('i', 'j', 'k')); - - expectObservable(result).toBe(expected, values); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should throw an error if not property is passed', () => { - expect(() => { - of({ prop: 1 }, { prop: 2 }).pipe(pluck()); - }).to.throw(Error, 'list of properties cannot be empty.'); - }); - - it('should propagate errors from observable that emits only errors', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' # '); - const e1subs = ' (^!)'; - const expected = '# '; - - const result = e1.pipe(pluck('whatever')); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should propagate errors from observable that emit values', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { a: { prop: '1' }, b: { prop: '2' } }; - const e1 = cold(' --a--b--#', inputs, 'too bad'); - const e1subs = ' ^-------!'; - const expected = '--1--2--#'; - - const result = e1.pipe(pluck('prop')); - - expectObservable(result).toBe(expected, undefined, 'too bad'); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should not pluck an empty observable', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' | '); - const e1subs = ' (^!)'; - const expected = '| '; - - const result = e1.pipe(pluck('whatever')); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should allow unsubscribing explicitly and early', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' --a--b--c--|', { a: { prop: '1' }, b: { prop: '2' } }); - const e1subs = ' ^-----! '; - const expected = '--1--2- '; - const unsub = ' ------! '; - - const result = e1.pipe(pluck('prop')); - - expectObservable(result, unsub).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should pluck twice', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { - a: { a: { b: { c: '1' } } }, - b: { a: { b: { c: '2' } } }, - c: { a: { b: { c: '3' } } }, - d: { a: { b: { c: '4' } } }, - e: { a: { b: { c: '5' } } }, - }; - const e1 = cold(' --a-b--c-d---e-|', inputs); - const e1subs = ' ^--------------!'; - const expected = '--1-2--3-4---5-|'; - - const result = e1.pipe(pluck('a', 'b'), pluck('c')); - - expectObservable(result).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should not break unsubscription chain when unsubscribed explicitly', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { a: { prop: '1' }, b: { prop: '2' } }; - const e1 = cold(' --a--b--c--|', inputs); - const e1subs = ' ^-----! '; - const expected = '--1--2- '; - const unsub = ' ------! '; - - const result = e1.pipe( - mergeMap((x) => of(x)), - pluck('prop'), - mergeMap((x) => of(x)) - ); - - expectObservable(result, unsub).toBe(expected); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should support symbols', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const sym = Symbol('sym'); - const inputs = { x: { [sym]: 'abc' } }; - - const e1 = cold(' --x--|', inputs); - const e1subs = ' ^----!'; - const expected = '--y--|'; - - const result = e1.pipe(pluck(sym)); - - expectObservable(result).toBe(expected, { y: 'abc' }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should not break on null values', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const inputs = { x: null }; - const e1 = cold(' --x--|', inputs); - const e1subs = ' ^----!'; - const expected = '--y--|'; - - const result = e1.pipe(pluck('prop')); - - expectObservable(result).toBe(expected, { y: undefined }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - - it('should stop listening to a synchronous observable when unsubscribed', () => { - const sideEffects: number[] = []; - const synchronousObservable = new Observable((subscriber) => { - // This will check to see if the subscriber was closed on each loop - // when the unsubscribe hits (from the `take`), it should be closed - for (let i = 0; !subscriber.closed && i < 10; i++) { - sideEffects.push(i); - subscriber.next(i); - } - }); - - synchronousObservable.pipe(pluck('whatever'), take(3)).subscribe(() => { - /* noop */ - }); - - expect(sideEffects).to.deep.equal([0, 1, 2]); - }); -}); diff --git a/src/index.ts b/src/index.ts index 0e75cb5323..b76cca1a77 100644 --- a/src/index.ts +++ b/src/index.ts @@ -147,7 +147,6 @@ export { min } from './internal/operators/min'; export { observeOn } from './internal/operators/observeOn'; export { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWith'; export { pairwise } from './internal/operators/pairwise'; -export { pluck } from './internal/operators/pluck'; export { raceWith } from './internal/operators/raceWith'; export { reduce } from './internal/operators/reduce'; export { repeat, RepeatConfig } from './internal/operators/repeat'; diff --git a/src/internal/operators/map.ts b/src/internal/operators/map.ts index 4d35b2187b..cf157a4081 100644 --- a/src/internal/operators/map.ts +++ b/src/internal/operators/map.ts @@ -30,7 +30,6 @@ import { createOperatorSubscriber } from './OperatorSubscriber'; * ``` * * @see {@link mapTo} - * @see {@link pluck} * * @param {function(value: T, index: number): R} project The function to apply * to each `value` emitted by the source Observable. The `index` parameter is diff --git a/src/internal/operators/pluck.ts b/src/internal/operators/pluck.ts deleted file mode 100644 index b80da73b6b..0000000000 --- a/src/internal/operators/pluck.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { map } from './map'; -import { OperatorFunction } from '../types'; - -/* tslint:disable:max-line-length */ -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck(k1: K1): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck(k1: K1, k2: K2): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck( - k1: K1, - k2: K2, - k3: K3 -): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck( - k1: K1, - k2: K2, - k3: K3, - k4: K4 -): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck< - T, - K1 extends keyof T, - K2 extends keyof T[K1], - K3 extends keyof T[K1][K2], - K4 extends keyof T[K1][K2][K3], - K5 extends keyof T[K1][K2][K3][K4] ->(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck< - T, - K1 extends keyof T, - K2 extends keyof T[K1], - K3 extends keyof T[K1][K2], - K4 extends keyof T[K1][K2][K3], - K5 extends keyof T[K1][K2][K3][K4], - K6 extends keyof T[K1][K2][K3][K4][K5] ->(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck< - T, - K1 extends keyof T, - K2 extends keyof T[K1], - K3 extends keyof T[K1][K2], - K4 extends keyof T[K1][K2][K3], - K5 extends keyof T[K1][K2][K3][K4], - K6 extends keyof T[K1][K2][K3][K4][K5] ->(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, ...rest: string[]): OperatorFunction; -/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */ -export function pluck(...properties: string[]): OperatorFunction; -/* tslint:enable:max-line-length */ - -/** - * Maps each source value to its specified nested property. - * - * Like {@link map}, but meant only for picking one of - * the nested properties of every emitted value. - * - * ![](pluck.png) - * - * Given a list of strings or numbers describing a path to a property, retrieves - * the value of a specified nested property from all values in the source - * Observable. If a property can't be resolved, it will return `undefined` for - * that value. - * - * ## Example - * - * Map every click to the tagName of the clicked target element - * - * ```ts - * import { fromEvent, pluck } from 'rxjs'; - * - * const clicks = fromEvent(document, 'click'); - * const tagNames = clicks.pipe(pluck('target', 'tagName')); - * - * tagNames.subscribe(x => console.log(x)); - * ``` - * - * @see {@link map} - * - * @param properties The nested properties to pluck from each source - * value. - * @return A function that returns an Observable of property values from the - * source values. - * @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. - */ -export function pluck(...properties: Array): OperatorFunction { - const length = properties.length; - if (length === 0) { - throw new Error('list of properties cannot be empty.'); - } - return map((x) => { - let currentProp: any = x; - for (let i = 0; i < length; i++) { - const p = currentProp?.[properties[i]]; - if (typeof p !== 'undefined') { - currentProp = p; - } else { - return undefined; - } - } - return currentProp; - }); -} diff --git a/src/operators/index.ts b/src/operators/index.ts index 7392d29aea..8a86e0ba52 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -53,7 +53,6 @@ export { observeOn } from '../internal/operators/observeOn'; export { onErrorResumeNextWith } from '../internal/operators/onErrorResumeNextWith'; export { pairwise } from '../internal/operators/pairwise'; export { partition } from '../internal/operators/partition'; -export { pluck } from '../internal/operators/pluck'; export { raceWith } from '../internal/operators/raceWith'; export { reduce } from '../internal/operators/reduce'; export { repeat, RepeatConfig } from '../internal/operators/repeat'; From 5569ef93597c1ceec0b81dfffbc8b88dd808c6c4 Mon Sep 17 00:00:00 2001 From: demensky Date: Wed, 25 Jan 2023 23:54:15 +0200 Subject: [PATCH 11/15] feat(observable): removed deprecated `pairs` function BREAKING CHANGE: The `pairs` function is no longer available. Use `from(Object.entries(obj))` instead `pairs(obj)`. --- .../assets/images/marble-diagrams/pairs.png | Bin 27559 -> 0 bytes spec-dtslint/operators/pairs-spec.ts | 26 ------ spec/index-spec.ts | 1 - spec/observables/pairs-spec.ts | 56 ------------ src/index.ts | 1 - src/internal/observable/pairs.ts | 84 ------------------ 6 files changed, 168 deletions(-) delete mode 100644 docs_app/src/assets/images/marble-diagrams/pairs.png delete mode 100644 spec-dtslint/operators/pairs-spec.ts delete mode 100644 spec/observables/pairs-spec.ts delete mode 100644 src/internal/observable/pairs.ts diff --git a/docs_app/src/assets/images/marble-diagrams/pairs.png b/docs_app/src/assets/images/marble-diagrams/pairs.png deleted file mode 100644 index 4a514e0cd3a2d063ae23b9ae8de46b3d163cc9ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27559 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 { - it('should work unscheduled', () => { - const o1 = pairs({ foo: 1, bar: 2 }); // $ExpectType Observable<["foo" | "bar", number]> - const o2 = pairs([1, 2, 3, 4]); // $ExpectType Observable<[string, number]> - const o3 = pairs(123); // $ExpectType Observable<[never, never]> - const o4 = pairs('blah'); // $ExpectType Observable<[string, string]> - const o5 = pairs({}); // $ExpectType Observable<[never, never]> - const o6 = pairs(true); // $ExpectType Observable<[never, never]> - const o7 = pairs(null); // $ExpectError - const o8 = pairs(undefined); // $ExpectError - }); - - it('should work scheduled', () => { - const o1 = pairs({ foo: 1, bar: 2 }, asyncScheduler); // $ExpectType Observable<["foo" | "bar", number]> - const o2 = pairs([1, 2, 3, 4], asyncScheduler); // $ExpectType Observable<[string, number]> - const o3 = pairs(123, asyncScheduler); // $ExpectType Observable<[never, never]> - const o4 = pairs('blah', asyncScheduler); // $ExpectType Observable<[string, string]> - const o5 = pairs({}, asyncScheduler); // $ExpectType Observable<[never, never]> - const o6 = pairs(true, asyncScheduler); // $ExpectType Observable<[never, never]> - const o7 = pairs(null, asyncScheduler); // $ExpectError - const o8 = pairs(undefined, asyncScheduler); // $ExpectError - }); -}); diff --git a/spec/index-spec.ts b/spec/index-spec.ts index 53d56a4a83..117f8b9fbb 100644 --- a/spec/index-spec.ts +++ b/spec/index-spec.ts @@ -65,7 +65,6 @@ describe('index', () => { expect(index.merge).to.exist; expect(index.of).to.exist; expect(index.onErrorResumeNext).to.exist; - expect(index.pairs).to.exist; expect(index.race).to.exist; expect(index.range).to.exist; expect(index.throwError).to.exist; diff --git a/spec/observables/pairs-spec.ts b/spec/observables/pairs-spec.ts deleted file mode 100644 index 078b96f9f3..0000000000 --- a/spec/observables/pairs-spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** @prettier */ -import { expect } from 'chai'; -import { TestScheduler } from 'rxjs/testing'; -import { pairs } from 'rxjs'; -import { observableMatcher } from '../helpers/observableMatcher'; - -describe('pairs', () => { - let rxTestScheduler: TestScheduler; - - beforeEach(() => { - rxTestScheduler = new TestScheduler(observableMatcher); - }); - - it('should create an observable emits key-value pair', () => { - rxTestScheduler.run(({ expectObservable }) => { - const e1 = pairs({ a: 1, b: 2 }); - const expected = '(ab|)'; - const values = { - a: ['a', 1], - b: ['b', 2], - }; - - expectObservable(e1).toBe(expected, values); - }); - }); - - it('should create an observable without scheduler', (done) => { - let expected = [ - ['a', 1], - ['b', 2], - ['c', 3], - ]; - - pairs({ a: 1, b: 2, c: 3 }).subscribe({ - next: (x) => { - expect(x).to.deep.equal(expected.shift()); - }, - error: (x) => { - done(new Error('should not be called')); - }, - complete: () => { - expect(expected).to.be.empty; - done(); - }, - }); - }); - - it('should work with empty object', () => { - rxTestScheduler.run(({ expectObservable }) => { - const e1 = pairs({}); - const expected = '|'; - - expectObservable(e1).toBe(expected); - }); - }); -}); diff --git a/src/index.ts b/src/index.ts index b76cca1a77..50d85a3eff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -73,7 +73,6 @@ export { interval } from './internal/observable/interval'; export { merge } from './internal/observable/merge'; export { of } from './internal/observable/of'; export { onErrorResumeNext } from './internal/observable/onErrorResumeNext'; -export { pairs } from './internal/observable/pairs'; export { partition } from './internal/observable/partition'; export { race } from './internal/observable/race'; export { range } from './internal/observable/range'; diff --git a/src/internal/observable/pairs.ts b/src/internal/observable/pairs.ts deleted file mode 100644 index 766ac81743..0000000000 --- a/src/internal/observable/pairs.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Observable } from '../Observable'; -import { scheduled } from '../scheduled/scheduled'; -import { SchedulerLike } from '../types'; -import { from } from './from'; - -/** - * @deprecated Use `from(Object.entries(obj))` instead. Will be removed in v8. - */ -export function pairs(arr: readonly T[], scheduler?: SchedulerLike): Observable<[string, T]>; -/** - * @deprecated Use `from(Object.entries(obj))` instead. Will be removed in v8. - */ -export function pairs>(obj: O, scheduler?: SchedulerLike): Observable<[keyof O, O[keyof O]]>; -/** - * @deprecated Use `from(Object.entries(obj))` instead. Will be removed in v8. - */ -export function pairs(iterable: Iterable, scheduler?: SchedulerLike): Observable<[string, T]>; -/** - * @deprecated Use `from(Object.entries(obj))` instead. Will be removed in v8. - */ -export function pairs( - n: number | bigint | boolean | ((...args: any[]) => any) | symbol, - scheduler?: SchedulerLike -): Observable<[never, never]>; - -/** - * Convert an object into an Observable of `[key, value]` pairs. - * - * Turn entries of an object into a stream. - * - * ![](pairs.png) - * - * `pairs` takes an arbitrary object and returns an Observable that emits arrays. Each - * emitted array has exactly two elements - the first is a key from the object - * and the second is a value corresponding to that key. Keys are extracted from - * an object via `Object.keys` function, which means that they will be only - * enumerable keys that are present on an object directly - not ones inherited - * via prototype chain. - * - * By default, these arrays are emitted synchronously. To change that you can - * pass a {@link SchedulerLike} as a second argument to `pairs`. - * - * ## Example - * - * Converts an object to an Observable - * - * ```ts - * import { pairs } from 'rxjs'; - * - * const obj = { - * foo: 42, - * bar: 56, - * baz: 78 - * }; - * - * pairs(obj).subscribe({ - * next: value => console.log(value), - * complete: () => console.log('Complete!') - * }); - * - * // Logs: - * // ['foo', 42] - * // ['bar', 56] - * // ['baz', 78] - * // 'Complete!' - * ``` - * - * ### Object.entries required - * - * In IE, you will need to polyfill `Object.entries` in order to use this. - * [MDN has a polyfill here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) - * - * @param {Object} obj The object to inspect and turn into an - * Observable sequence. - * @param {Scheduler} [scheduler] An optional IScheduler to schedule - * when resulting Observable will emit values. - * @returns {(Observable>)} An observable sequence of - * [key, value] pairs from the object. - * @deprecated Use `from(Object.entries(obj))` instead. Will be removed in v8. - */ -export function pairs(obj: any, scheduler?: SchedulerLike) { - const entries = Object.entries(obj); - return scheduler ? scheduled(entries, scheduler) : from(entries); -} From b65ba192df585fbf42668ac39fbf000537a104b6 Mon Sep 17 00:00:00 2001 From: demensky Date: Fri, 10 Feb 2023 20:26:36 +0200 Subject: [PATCH 12/15] chore: remove duplication in `ApiUnion` --- docs_app/tools/decision-tree-generator/src/lib/interfaces.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts index d30efa18e6..32b0756d1b 100644 --- a/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts +++ b/docs_app/tools/decision-tree-generator/src/lib/interfaces.ts @@ -22,7 +22,6 @@ export type ApiUnion = | 'catchError' | 'combineLatest' | 'concat' - | 'concat' | 'concatMap' | 'concatMapTo' | 'count' From 2cc538e9f23d135a03efbf0c87e42b0d67db6679 Mon Sep 17 00:00:00 2001 From: demensky Date: Fri, 10 Feb 2023 20:51:17 +0200 Subject: [PATCH 13/15] docs: remove mentions of non-existent `cache` operator --- docs_app/content/guide/scheduler.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs_app/content/guide/scheduler.md b/docs_app/content/guide/scheduler.md index 22d76b473c..e462222c37 100644 --- a/docs_app/content/guide/scheduler.md +++ b/docs_app/content/guide/scheduler.md @@ -144,6 +144,4 @@ Because RxJS uses the least concurrency scheduler, you can pick a different sche Time-related operators like `bufferTime`, `debounceTime`, `delay`, `auditTime`, `sampleTime`, `throttleTime`, `timeInterval`, `timeout`, `timeoutWith`, `windowTime` all take a Scheduler as the last argument, and otherwise operate by default on the `asyncScheduler`. -Other instance operators that take a Scheduler as argument: `cache`, `combineLatest`, `concat`, `expand`, `merge`, `startWith`. - -Notice that `cache` accept a Scheduler because they utilize a ReplaySubject. The constructor of a ReplaySubjects takes an optional Scheduler as the last argument because ReplaySubject may deal with time, which only makes sense in the context of a Scheduler. By default, a ReplaySubject uses the `queueScheduler` Scheduler to provide a clock. +Other instance operators that take a Scheduler as argument: `combineLatest`, `concat`, `expand`, `merge`, `startWith`. From a95a44e30e053cc489eb65589d5ba95a4924e72e Mon Sep 17 00:00:00 2001 From: demensky Date: Fri, 10 Feb 2023 21:09:17 +0200 Subject: [PATCH 14/15] docs: use `EMPTY` instead `empty` --- docs_app/content/guide/operators.md | 2 +- src/internal/operators/defaultIfEmpty.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index 404bf19bee..dddc5849a8 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -119,7 +119,7 @@ For a complete overview, see the [references page](/api). - [`bindCallback`](/api/index/function/bindCallback) - [`bindNodeCallback`](/api/index/function/bindNodeCallback) - [`defer`](/api/index/function/defer) -- [`empty`](/api/index/function/empty) +- [`EMPTY`](/api/index/const/EMPTY) - [`from`](/api/index/function/from) - [`fromEvent`](/api/index/function/fromEvent) - [`fromEventPattern`](/api/index/function/fromEventPattern) diff --git a/src/internal/operators/defaultIfEmpty.ts b/src/internal/operators/defaultIfEmpty.ts index 9e0d277e27..3cf04e7ddc 100644 --- a/src/internal/operators/defaultIfEmpty.ts +++ b/src/internal/operators/defaultIfEmpty.ts @@ -28,7 +28,7 @@ import { createOperatorSubscriber } from './OperatorSubscriber'; * result.subscribe(x => console.log(x)); * ``` * - * @see {@link empty} + * @see {@link EMPTY} * @see {@link last} * * @param defaultValue The default value used if the source From 6dddca56b06cc395bd5a98b5e9749bb5353bbb30 Mon Sep 17 00:00:00 2001 From: demensky Date: Fri, 10 Feb 2023 21:12:39 +0200 Subject: [PATCH 15/15] docs: use `ObservableNotification` instead `Notification` --- src/internal/operators/materialize.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internal/operators/materialize.ts b/src/internal/operators/materialize.ts index f642415d52..53f2a3c57f 100644 --- a/src/internal/operators/materialize.ts +++ b/src/internal/operators/materialize.ts @@ -5,11 +5,11 @@ import { createOperatorSubscriber } from './OperatorSubscriber'; /** * Represents all of the notifications from the source Observable as `next` - * emissions marked with their original types within {@link Notification} + * emissions marked with their original types within {@link ObservableNotification} * objects. * * Wraps `next`, `error` and `complete` emissions in - * {@link Notification} objects, emitted as `next` on the output Observable. + * {@link ObservableNotification} objects, emitted as `next` on the output Observable. * * * ![](materialize.png) @@ -44,11 +44,11 @@ import { createOperatorSubscriber } from './OperatorSubscriber'; * // - Notification { kind: 'E', value: undefined, error: TypeError { message: x.toUpperCase is not a function }, hasValue: false } * ``` * - * @see {@link Notification} + * @see {@link ObservableNotification} * @see {@link dematerialize} * * @return A function that returns an Observable that emits - * {@link Notification} objects that wrap the original emissions from the + * {@link ObservableNotification} objects that wrap the original emissions from the * source Observable with metadata. */ export function materialize(): OperatorFunction> {