-
-
Notifications
You must be signed in to change notification settings - Fork 420
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
Fix driver race condition on sinks, fix DOM driver mutations in loop #719
Conversation
|
@jvanbruegge Yes, I was aware but forgot to mention it. We already don't support IE9, but IE10 can support this through a polyfill |
What kills IE9? |
@jvanbruegge There's an issue about it, still open. (I'm now on mobile, harder to search) |
It was this issue: #224 |
To-do according to CI failures:
|
fb60545
to
1990864
Compare
1475ca5
to
05172a3
Compare
19355d6
to
61f81cf
Compare
05172a3
to
ce31173
Compare
I'm considering dropping official support for IE10. I added a MutationObserver polyfill when testing IE10, and most tests passed, but tests related to DocumentFragment didn't pass. I think the MutationObserver polyfill can't detect that a DocumentFragment was mutated because fragments are by definition "detached" from the normal document, maybe that's why it can't detect mutations. DocumentFragments and Cycle.js in IE10 would only be used for Web Components (I think), so I think it's fair to not support Cycle.js + Web Components in IE10, but normal Cycle.js DOM usage (without Web Components) would still work. |
This changes the internal workings of Cycle Run so that sink proxies are normal xstream streams, not MemoryStreams. BREAKING CHANGE: This is a breaking change that requires updating your project to use the latest Cycle Run as well as the latest Cycle HTTP and Cycle DOM all at the same time, otherwise you may see race conditions across drivers. ISSUES CLOSED: #592
Every sink stream emission from the main() is scheduled on the microtask available (MutationObserver or process.nextTick or setTimeout) in order to give enough time for subscriptions to happen in main() and avoid race conditions such as issue #592. BREAKING CHANGE: This means Cycle run() function is no longer synchronous, so if for some reason you were depending on the synchronicity of run(), you will lose this guarantee. This is breaking change, but rarely should this be experienced. With the new microtask scheduling, sinks are emitted to drivers as soon as the current event loop scripts are completed, so there will not be noticeable delays in the user interface (like setTimeout would incur). ISSUES CLOSED: #592
BREAKING CHANGE: Like Cycle run() v4, RxJS run() will not anymore execute synchronously once the run() function is called, instead it will schedule sink emissions as microtasks that happen as soon as the current event loop scripts are completed.
// exist before elementAfterPatch$ calls mutationObserver.observe() | ||
mutationConfirmed$.addListener({}); | ||
|
||
const elementAfterPatch$ = firstRoot$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite convoluted, and I'm sure this could be resolved with adding a scheduler to xtream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convoluted: merge -> map -> fold -> drop -> map -> startWith -> map -> compose
, each with various degrees of complexity. It is hard to reason about. Smaller steps where the outputs of the various operations are assigned to well-named variables makes it much easier for anyone who didn't write this code to understand it. Either that or apply some comments that explain the why.
I believe scheduling is a solution to #592, but not for #699 (which this code right here is about)
Fair enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it's a long chain of operators. And yes, one can easily refactor that by just splitting it up and placing them in convenient helper functions. Has nothing to do with schedulers, though.
Good that I understood your comment is about code style, not about the actual fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scheduler mention is related to this PR, as the PR references #592 explicitly. It may not have a direct impact on this patch solution, but indirectly it definitely has. IMO, it is an underlying issue with xstream. For example, Most.js doesn’t emit during Stream.run
, and I think that the same behavior applied to xstream would be the solution to all these issues. Just my two cents.
Of course, if this is just a temporary patch that will be addressed again later when #592 is handled, then I understand the approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Frikki, most.js also has scheduling problems: cujojs/most#414
And adding a trampoling scheduler (like RxJS 4 had) has its downsides too. This PR has a comprehensive solution without introducing a scheduler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To that end, I do not agree with the solution. As you know, we are working intensively with Motorcycle and @most/core
. We do not have these issues. But it’s fine if Cycle.js and xstream want things implemented differently. After all, Cycle.js and Motorcycle are not the same, though they deal with the same concept. Thanks for the feedback.
When vnode$ depends on element$ and vice-versa, a synchronous infinite loop might occur, which is issue #699. This commit solves that by using MutationObserver, used to indicate when to emit a new element on element$. BREAKING CHANGE: Internet Explorer 10 is no longer officially supported, but it can still be used with cycle/dom under some circumstances. You should use a polyfill for MutationObserver and make sure you are not rendering the application in a DocumentFragment as the container node. Only under those conditions will cycle/dom should work correctly in IE10. ISSUES CLOSED: #699
baf1a95
to
6004260
Compare
6004260
to
28243b7
Compare
Travis CI tests pass. @jvanbruegge could you give a final review? |
I hope someone can take a look at this before merging, because it has some important breaking changes and fixes. I know it's a big PR but it's easier to review commit by commit. There are only 3 important commits actually: |
This looks good to me too. I just experienced this issue again in a new context. Onion |
Thanks @ntilwalli and @jvanbruegge ! |
make test FOO
for the package FOO I'm modifyingmake commit
instead ofgit commit