-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: chain subscriptions from interop observables (#5059)
* test: add failing tests for interop observables * fix: check for interop subscriptions * chore: make subscribeToResult signatures safer * chore: add test comments * chore: add implementation comments
- Loading branch information
Showing
17 changed files
with
311 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { expect } from 'chai'; | ||
import { Observable, of, Subscriber } from 'rxjs'; | ||
import { observable as symbolObservable } from 'rxjs/internal/symbol/observable'; | ||
import { rxSubscriber as symbolSubscriber } from 'rxjs/internal/symbol/rxSubscriber'; | ||
import { asInteropObservable, asInteropSubscriber } from './interop-helper'; | ||
|
||
describe('interop helper', () => { | ||
it('should simulate interop observables', () => { | ||
const observable = asInteropObservable(of(42)); | ||
expect(observable).to.not.be.instanceOf(Observable); | ||
expect(observable[symbolObservable]).to.be.a('function'); | ||
}); | ||
|
||
it('should simulate interop subscribers', () => { | ||
const subscriber = asInteropSubscriber(new Subscriber()); | ||
expect(subscriber).to.not.be.instanceOf(Subscriber); | ||
expect(subscriber[symbolSubscriber]).to.be.undefined; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Observable, Subscriber, Subscription } from 'rxjs'; | ||
import { rxSubscriber as symbolSubscriber } from 'rxjs/internal/symbol/rxSubscriber'; | ||
|
||
/** | ||
* Returns an observable that will be deemed by this package's implementation | ||
* to be an observable that requires interop. The returned observable will fail | ||
* the `instanceof Observable` test and will deem any `Subscriber` passed to | ||
* its `subscribe` method to be untrusted. | ||
*/ | ||
export function asInteropObservable<T>(observable: Observable<T>): Observable<T> { | ||
return new Proxy(observable, { | ||
get(target: Observable<T>, key: string | number | symbol) { | ||
if (key === 'subscribe') { | ||
const { subscribe } = target; | ||
return interopSubscribe(subscribe); | ||
} | ||
return Reflect.get(target, key); | ||
}, | ||
getPrototypeOf(target: Observable<T>) { | ||
const { subscribe, ...rest } = Object.getPrototypeOf(target); | ||
return { | ||
...rest, | ||
subscribe: interopSubscribe(subscribe) | ||
}; | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Returns a subscriber that will be deemed by this package's implementation to | ||
* be untrusted. The returned subscriber will fail the `instanceof Subscriber` | ||
* test and will not include the symbol that identifies trusted subscribers. | ||
*/ | ||
export function asInteropSubscriber<T>(subscriber: Subscriber<T>): Subscriber<T> { | ||
return new Proxy(subscriber, { | ||
get(target: Subscriber<T>, key: string | number | symbol) { | ||
if (key === symbolSubscriber) { | ||
return undefined; | ||
} | ||
return Reflect.get(target, key); | ||
}, | ||
getPrototypeOf(target: Subscriber<T>) { | ||
const { [symbolSubscriber]: symbol, ...rest } = Object.getPrototypeOf(target); | ||
return rest; | ||
} | ||
}); | ||
} | ||
|
||
function interopSubscribe<T>(subscribe: (...args: any[]) => Subscription) { | ||
return function (this: Observable<T>, ...args: any[]): Subscription { | ||
const [arg] = args; | ||
if (arg instanceof Subscriber) { | ||
return subscribe.call(this, asInteropSubscriber(arg)); | ||
} | ||
return subscribe.apply(this, args); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.