-
Notifications
You must be signed in to change notification settings - Fork 3k
Observables cannot be passed between window contexts. #2628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
eliminate use of instanceof to support passing observables between javascript contexts Closes ReactiveX#2628
I'm feeling kind of similar to what bacon.js did. Checking properties in observable is not robust way (yes, even |
At the end of the issue I referenced, bacon.js accepted a PR which eliminated the use of instanceof for testing Observable identity. After a quick browse at their HEAD, master still seems to have those changes incorporated. Also, this project already acknowledges the interop point defined by the es7-observable spec, which I interpret as implying compatibility with external implementations of Observable. Currently, such compatibility is broken due to use of |
I agree that we should rely less on instanceof and use duck-typing instead. I know it's not robust, but JavaScript itself isn't robust. |
When instrumenting Rx for RxFiddle i've stumbled on this issue too. RxFiddle possibly uses a different instance of Rx than the instrumented target, which might be a small minified and tree-shaken module that contains a small subset of Rx. I've not really settled how to solve solve it. For now I just use only the types of Rx ( I agree with @goldsam however that Rx should interop with the es7 Observables. Just out of the box and by only looking at the contract (subscribe, next, error, complete). |
Actually we should not rely on I'd argue for using a combination such as checking for |
The idea of Rx is to have a subscribe method on the Observable taking an Observer with a next, error and complete method. As long as you put in something that works with that we should be fine right? In what cases does Rx use instanceof? Mostly in cases where we need to check whether we can use some optimization? Why should Rx not work directly with Most, xstream, etc? |
@hermanbanken through the ES Observable spec it indeed does work directly. The problem is when a window context receiving an Observable expects that Observable to be a real RxJS v5 Observable including things like the |
I might not have been clear.
When does this occur? The original question gives this example: window.myObservable
.switchMap(function(x) {
return Rx.Observable.of(x);
})
.subscribe(function(x) {
console.log(x);
}); here we see that it is
The only thing that switchMap needs to verify is that I think the danger comes from use cases like this: import map from "rxjs/operators/map"
let mappedOnce = window.parent.myObservable.map(x => x * x)
let mappedTwice = map.call(mappedOnce, x => x + 1) That way two unrelated (by prototype) Observables are joined by creating one with composed selectors. Users of rxjs need to know how map is implemented in that case to understand what scope |
@hermanbanken I'm not so sure I understand, pardon me if I say something that doesn't make sense. As far as I understand, window.myObservable
.switchMap(function(x) {
return Rx.Observable.of(x); // <----- this line
})
.subscribe(function(x) {
console.log(x);
}); runs in the same window context as the switchMap: window.myObservable
.switchMap(function(x) { // <----- this operator
return Rx.Observable.of(x);
})
.subscribe(function(x) {
console.log(x);
}); and the switchMap receives |
They run in the same window context, but originate from a different window I believe. Let's differentiate between window A and window B, with The // running in window A
window.myObservable // <---- from context B, previously assigned
.switchMap(function(x) { // <---- from context B
let X = Rx.Observable.of(x); // <----- run in window A, using Rx from context A
return X;
})
.subscribe(function(x) {
console.log(x);
});
Or am I mistaken? |
Understood, you're correct. And I just went through many operators and I don't think we will have a case where we would need to duck-type check for the existence of |
Ah good to see that I was not just going crazy 😜 . I think this is related to #2489 too, since things would get more complicated if we do this: import switchMap from 'rxjs/somewhere/switchMap'
window.myObservable // <---- from context B, previously assigned
.pipe(switchMap(function(x) { // <---- pipe from context B, switchMap from context A
let X = Rx.Observable.of(x); // <----- run in window A, using Rx from context A
return X;
}))
.subscribe(function(x) {
console.log(x);
}); at that point |
A few things:
You can solve the problem outlined in your original post with a simple if (window.opener) {
window.myObservable = Rx.Observable.from(window.opener.myObservable);
} else {
window.myObservable = Rx.Observable.of(1, 2, 3);
window.open(location.href);
} Covering this corner case that has a simple workaround is probably not worth the performance cost. |
@benlesh ...
if (typeof ish[observable_1.observable] === 'function') {
if (ish instanceof Observable_1.Observable && !scheduler) {
return ish;
}
return new FromObservable(ish, scheduler);
} ... Do you see a way to easily work around this without library support? |
@benlesh Any help on this would be appreciated, trying to get the exact same piece work for my app - ng4.0, rxjs 5.0.2 |
Changes the instanceof check for rxjs to a duck-typing isObservable method to fix mistakenly rejecting Observables from other contexts. Window context issue: ReactiveX/rxjs#2628
Hi everyone any update on this? |
If it can be of any help, I couldn't make it work with Observable.from(originalObservable); But I got it working with Observable.create(observer => originalObservable.subscribe(observer)) |
@marceloemanoel your workaround is the best I've seen for this so far. Unfortunately, we as a library can't just declare that everything with a I think your workaround will be as good as it can get for now. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
RxJS version: 5.4
Code to reproduce:
Expected behavior:
Both parent and child window should print 1, 2, 3 to the console.
Actual behavior:
The child window throws an exception because
myObservable
from the parent window's context cannot be identified as an Observable in the child window's context.Additional information:
The issue is caused by a reliance on
instanceof
for determining if an object is an Observable which fails for objects passed between javascript contexts. Instead, a more robust solution would test for the shape of an Observable, perhaps using a type guard similar toisPromise
The text was updated successfully, but these errors were encountered: