Skip to content
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

Conversation

rwjblue
Copy link
Member

@rwjblue rwjblue commented Nov 5, 2019

Given this template:

<p>{{#if true}}<div></div>{{/if}}</p>

The browser auto-corrects it to:

<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.


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:

@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from fa591b0 to 4af59c4 Compare November 6, 2019 22:59
@rwjblue
Copy link
Member Author

rwjblue commented Nov 6, 2019

CI is failing on IE11 for bizarro ways because IE11 doesn't insert an end </p> the same way modern browsers do.

With IE11, the following <p>hello <div>world</div></p> is "corrected" to <p>hello <div>world!</div><p></p>, but on modern browsers we get <p>hello </p><div>world!</div><p></p>. 🙀

@scalvert
Copy link
Contributor

scalvert commented Nov 6, 2019

👍

@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from 4af59c4 to 55b7825 Compare November 7, 2019 02:08
rwjblue added a commit to rwjblue/-demo-disabling-rerendering-in-ssr-mode that referenced this pull request Nov 7, 2019
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from e5793cf to 55b7825 Compare November 7, 2019 17:00
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch 2 times, most recently from c7a9e4c to a9ea31e Compare November 8, 2019 02:46
@@ -516,7 +545,7 @@ class Rehydration extends AbstractRehydrationTests {
remoteParent: clientRemoteParent,
remoteChild: clientRemoteChild,
});
this.assertRehydrationStats({ nodesRemoved: 2 });
this.assertRehydrationStats({ nodesRemoved: 0 });
Copy link
Member Author

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 });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from a9ea31e to 00ce6ef Compare November 8, 2019 03:12
@rwjblue rwjblue changed the title Failing rehydration test for <p>{{#if true}}<div></div>{{/if}}</p> Refactor RehydrateBuilder to be more robust Nov 8, 2019
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from 00ce6ef to 76442d9 Compare November 8, 2019 03:30
Copy link
Member

@chadhietala chadhietala left a 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;
Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

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?

Copy link
Member Author

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).

@kratiahuja
Copy link

👍

rwjblue and others added 3 commits November 8, 2019 15:04
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>
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from 76442d9 to 9a5d2c0 Compare November 8, 2019 20:18
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from 9a5d2c0 to f32876c Compare November 12, 2019 20:39
rwjblue and others added 4 commits November 20, 2019 09:23
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>
@rwjblue rwjblue force-pushed the failing-test-for-closing-blocks-during-auto-correct-mismatch branch from 47b06ab to 31680b6 Compare November 20, 2019 14:58
@rwjblue rwjblue dismissed krisselden’s stale review November 20, 2019 21:48

addressed issue

@rwjblue rwjblue merged commit 2abbe46 into glimmerjs:master Nov 22, 2019
@rwjblue rwjblue deleted the failing-test-for-closing-blocks-during-auto-correct-mismatch branch November 22, 2019 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants