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

fix(ivy): ViewRef.rootNodes returns rootNodes from child views as well #33457

Closed
wants to merge 5 commits into from

Conversation

mhevery
Copy link
Contributor

@mhevery mhevery commented Oct 28, 2019

The idea behind rootNodes is to return all of the nodes which need
to be added to the DOM in order for the ViewRef to be rendered.
The new implementation correctly takes into account the case where
one of the rootNodes is a container containing other ViewRefs.

…ell.

The idea behind `rootNodes` is to return all of the nodes which need
to be added to the DOM in order for the `ViewRef` to be rendered.
The new implementation correctly takes into account the case where
one of the rootNodes is a container containing other `ViewRef`s.
@mhevery mhevery requested a review from a team as a code owner October 28, 2019 23:58
@mhevery mhevery added action: merge The PR is ready for merge by the caretaker target: major This PR is targeted for the next major release action: review The PR is still awaiting reviews from at least one requested reviewer labels Oct 28, 2019
if (tNodeChild.type === TNodeType.ElementContainer) {
collectNativeNodes(lView, tNodeChild, result);
} else if (tNodeChild.type === TNodeType.Projection) {
if (tNode.type === TNodeType.ElementContainer) {

Choose a reason for hiding this comment

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

I don't see a test for the TNodeType.IcuContainer in the series of node type checks. If I recall properly ICU containers "behave" similarly to <ng-container>s. I'm not sure if we can bump into ICU containers here, but:

  • if no, we should add an assert;
  • if yes, we should add a test + handle this case.

Choose a reason for hiding this comment

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

Also, I would add an assert to verify that we don't bump into tNode being TNodeType.View (just for completeness, to make sure that we are not missing handling of any TNode type).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • I have added asserts
  • Added tests and was not able to get Icu node to show up here.

selector: 'edit-form',
template: `
<ng-template [dir]="true">
<div *ngIf="true">Text</div>

Choose a reason for hiding this comment

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

Could we add few more test cases:

  • nested <ng-container>s at the root of an embedded view;
  • ICU inside <ng-container> - I'm not sure if we can have them at the root of a view;
  • a directive that asks for a ViewContainerRef at the root of a view (you've got a case where a VCRef is asked on a container);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added test cases

Choose a reason for hiding this comment

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

I haven't seen a test for the case where a ViewContainerRef is injected on a regular element.

Copy link
Member

@pkozlowski-opensource pkozlowski-opensource left a comment

Choose a reason for hiding this comment

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

Did the first pass. The direction LGTM but I'm not sure if we are handling all the cases of nodes that can be at the root of a view (left comments enumerating those cases). As the very minimum we need more tests.

Copy link
Contributor Author

@mhevery mhevery left a comment

Choose a reason for hiding this comment

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

Updated, PTAL

if (tNodeChild.type === TNodeType.ElementContainer) {
collectNativeNodes(lView, tNodeChild, result);
} else if (tNodeChild.type === TNodeType.Projection) {
if (tNode.type === TNodeType.ElementContainer) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • I have added asserts
  • Added tests and was not able to get Icu node to show up here.

selector: 'edit-form',
template: `
<ng-template [dir]="true">
<div *ngIf="true">Text</div>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

added test cases

} else if (tNode.type === TNodeType.Container) {
const lContainer = lView[tNode.index];
const containerTView = tNode.tViews !as TView;
ngDevMode && assertDefined(containerTView, 'TView expected');

Choose a reason for hiding this comment

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

I don't think that this assert is correct for 2 reasons:

  • it refers to a TView defined by this <ng-template> and not inserted into a ViewContainerRef asked on this <ng-template>;
  • many different types of TViews can be inserted into one container so we can't assume that all inserted views share the same TView
  • it can be null when the definition is empty <ng-template></ng-template>, AFAIK

There is a confusion between an embedded view defintion and the the inserted instance here.

<ng-template [dir]="true">
<div *ngIf="true">Text</div>
<ng-container>container-content</ng-container>
<div i18n>assert TNodeType.IcuContainer is never a root node</div>

Choose a reason for hiding this comment

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

This is not enough, you need to have an actual ICU expression inside an element with the i18n attribute. Also, having div at the root is not enough as a <div> is a root node so no need to descend any further. An example way of testing it would be <ng-container i18n>Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {several minutes ago}}</ng-container> and here we need to descent into the ICU container.

tl;dr; I still believe that we need to handle the case of a ICU container.

while (tNode) {
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Element, TNodeType.Container, TNodeType.Projection,
TNodeType.ElementContainer);

Choose a reason for hiding this comment

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

I believe that we need to handle a ICU container, see: https://github.com/angular/angular/pull/33457/files#r340598750

Copy link
Member

@pkozlowski-opensource pkozlowski-opensource left a comment

Choose a reason for hiding this comment

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

@mhevery I still believe that there are tests / use-cases missing. How about we review / merge #33493 instead that has all the test I could think of (+ fixes for those)?

@mhevery
Copy link
Contributor Author

mhevery commented Oct 30, 2019

Closing in as @pkozlowski-opensource took over #33493

@mhevery mhevery closed this Oct 30, 2019
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker action: review The PR is still awaiting reviews from at least one requested reviewer cla: yes target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants