-
Notifications
You must be signed in to change notification settings - Fork 190
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
Refactor RehydrateBuilder to be more robust #988
Refactor RehydrateBuilder to be more robust #988
Conversation
fa591b0
to
4af59c4
Compare
CI is failing on IE11 for bizarro ways because IE11 doesn't insert an end With IE11, the following |
👍 |
4af59c4
to
55b7825
Compare
e5793cf
to
55b7825
Compare
c7a9e4c
to
a9ea31e
Compare
@@ -516,7 +545,7 @@ class Rehydration extends AbstractRehydrationTests { | |||
remoteParent: clientRemoteParent, | |||
remoteChild: clientRemoteChild, | |||
}); | |||
this.assertRehydrationStats({ nodesRemoved: 2 }); | |||
this.assertRehydrationStats({ nodesRemoved: 0 }); |
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 PR fixes rehydration for in-element, that is why this goes to expect no removed nodes.
toInnerHTML(clientRemote), | ||
'<prefix></prefix><suffix></suffix><inner>Wat Wat</inner>' | ||
); | ||
this.assertRehydrationStats({ nodesRemoved: 2 }); |
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.
Using {{in-element
without passing insertBefore
as a named argument always means "clear this element".
a9ea31e
to
00ce6ef
Compare
<p>{{#if true}}<div></div>{{/if}}</p>
00ce6ef
to
76442d9
Compare
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.
Overall looks good, just a couple of questions and a nit.
// `window.ActiveXObject` is "falsey" in IE11 (but not `undefined` or `false`) | ||
// `"ActiveXObject" in window` returns `true` in all IE versions | ||
// only IE11 will pass _both_ of these conditions | ||
const isIE11 = !(window as any).ActiveXObject && 'ActiveXObject' in window; |
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.
It would be good to annotate this stuff so it's easy to cleanup in a #worldwithoutIE11.
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.
Happy to! How do you think I should annotate?
private blockDepth = 0; | ||
|
||
// private candidate: Option<SimpleNode> = null; | ||
blockDepth = 0; |
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.
Is the only reason why this has to be public
is to enforce the type on L101?
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.
Yes, if it is private
the "special" types that we added for pushElement
won't work. The real issue is that NewElementBuilder
(our super class) invokes this.pushElement
during RehydrateBuilder
's super()
call which means our class fields haven't ran yet (and therefore this.blockDepth
is undefined
still). So we tried to make the types such that it was clearer that the this
within that method was "weird" (to avoid future mistakes).
👍 |
Given this template: ```hbs <p>{{#if true}}<div></div>{{/if}}</p> ``` The browser auto-corrects it to: ```html <p></p><div></div><p></p> ``` When the rehydration builder runs against this, it throws an error (and fails to continue rehydrating) leaving the app in a broken state.
Co-authored-by: Kris Selden <kselden@linkedin.com>
76442d9
to
9a5d2c0
Compare
9a5d2c0
to
f32876c
Compare
Ensure that updates of `currentCursor.candidate` go through the custom setter for `candidate`. This fixes a number of issues caused by having the wronge `currentCursor.nextSibling` (and therefore not properly rehydrating). Also ensures that `in-element` _can actually_ rehydrate. Prior to this commit we would (nearly universally) clear the target contents. See updated test cases ensuring `0` nodes removed for samples. Co-authored-by: Kris Selden <kselden@linkedin.com>
Co-authored-by: Kris Selden <kselden@linkedin.com>
Previously, we would clear to the cursors openBlockDepth but if rehydration is disabled, the currentCursor.openBlockDepth is not updated as we progress through additional `__openBlock` invocations (due to short curcuit returning). Instead of using the cursors notion of openBlockDepth we use the local `this.blockDepth` value (which is always maintained properly). Co-authored-by: Kris Selden <kselden@linkedin.com>
47b06ab
to
31680b6
Compare
Given this template:
The browser auto-corrects it to:
When the rehydration builder runs against this, it throws an error (and fails to continue rehydrating) leaving the app in a broken state.
This PR refactors a number of things about how
RehydrateBuilder
recovers from errors like the one mentioned above, it also fixes some fundamental issues with rehydration of{{in-element}}
usage (which was previously broken).After this refactor, the act of rehydration should never error (leaving the app in a horribly broken state). At worst, whatever amount of SSR'ed content has already been processed when a mismatch occurs will remain stable and the remainder of the content will be cleared just before we set up the new / correct DOM from the initial render.
Paired with @krisselden on most of the fixes / refactors in this PR.
TODO: