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

Issue 7084 - fix the compiler's "is recursive" check #8705

Merged
merged 1 commit into from Jun 22, 2016

Conversation

KiaraGrouwstra
Copy link
Contributor

@KiaraGrouwstra KiaraGrouwstra commented May 18, 2016

Please check if the PR fulfills these requirements

I'm not sure if there's much to add in terms of documentation for this fix. Feel free to correct.

I've written a test (based on the Plunker reproduction in the original issue), but I don't see a spec file for the runtime_compiler anymore. Moreover, I don't think my reproduction really qualifies as a compiler unit test, since it's a bit bigger in scope. So I'm not quite sure where you guys would prefer to have me put it -- I'd be glad to get some feedback on this then add it in as desired.

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

  • Bugfix

What is the current behavior? (You can also link to an open issue here)

See 7084: the compiler currently judges some mutually recursive component structures as non-recursive, which causes it to await non-resolving promises. As a result, in production it hangs without errors, in tests, createAsync just times out to Jasmine.

What is the new behavior?

I let the compiler check the current component's descendants as well, so as to reclassify the misjudged cases as recursive. This way, it no longer hangs/errors.

Does this PR introduce a breaking change?

  • No

Other information:

From what I can see, the offline compiler has no similar check. I also haven't found equivalent Dart code.

Note I have not yet re-run the test as asked in the guidelines. Like for some other non-Mac users (environment: Windows 10 + Vagrant Ubuntu VM that break on symlinks), building and running the test suite has proven a major barrier for me. I apologize for this, and hope Travis will do for now.

@@ -128,6 +128,11 @@ export class RuntimeCompiler implements ComponentResolver {
var childViewPipes: CompilePipeMetadata[] =
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
ListWrapper.forEachWithIndex(childViewDirectives.map(x => x.type.runtime), descendant => {
Copy link
Contributor

Choose a reason for hiding this comment

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

forEachWithIndex -> forEach however childViewDirectives.map().forEach(...) should work ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@vicb: whoops, thanks, fair point.

@vicb
Copy link
Contributor

vicb commented May 20, 2016

@tbosch could you please have a look at the PR and help @tycho01 to come up with a test ?

(@tycho01 please also squash your commits)

@KiaraGrouwstra
Copy link
Contributor Author

KiaraGrouwstra commented May 21, 2016

Here is the test I'd made based on the original issue (feedback welcome), though I wasn't very sure what might be the best place for it:

// non-returning tests in recursion: [#7084](https://github.com/angular/angular/issues/7084)

import { Component, forwardRef } from '@angular/core';
import { ComponentFixture, NgMatchers, inject, injectAsync, beforeEachProviders, it, fit, xit, expect, afterEach, beforeEach, } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { test_comp, asyncTest } from '../../../test';

@Component({
  selector: 'left',
  template: `L<right *ngIf="false"></right>`,
  directives: [
    forwardRef(() => RightComp),
  ]
})
class LeftComp {}

@Component({
  selector: 'right',
  template: `R<left *ngIf="false"></left>`,
  directives: [
    forwardRef(() => LeftComp),
  ]
})
class RightComp {}

@Component({
  selector: 'app',
  template: `[<left *ngIf="false"></left><right *ngIf="false"></right>]`,
  directives: [
    forwardRef(() => LeftComp),
    forwardRef(() => RightComp),
  ]
})
export class App {}

let cls = test_comp('app', App);

describe('7084', () => {
  let tcb;
  let test = (props, fn) => (done) => asyncTest(tcb, cls)(props, fn)(done);

  beforeEach(inject([TestComponentBuilder], (builder) => {
    tcb = builder;
  }));

  it('should work', test({}, ({ comp, el }) => {
    expect(el).toHaveText('[]');
  }));

});

I guess I'll squash them into one when the test is in as well.

@tbosch
Copy link
Contributor

tbosch commented Jun 9, 2016

This should go into regression_integration_spec (see https://github.com/angular/angular/blob/master/modules/@angular/core/test/linker/regression_integration_spec.ts).

The test looks good, but please add a bit more description than just the issue number.

@tbosch tbosch added pr_state: LGTM action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Jun 9, 2016
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm.

@googlebot
Copy link

CLAs look good, thanks!

@KiaraGrouwstra
Copy link
Contributor Author

KiaraGrouwstra commented Jun 10, 2016

@tbosch: I added the test, vicb's suggestion, and squashed. CI failed on build though... what could I do about that?

tcb.createAsync(FakeRecursiveComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('[]');
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a bit more expectations to see that the child components really work.

@tbosch
Copy link
Contributor

tbosch commented Jun 13, 2016

Sorry, master moved ahead, you need to rebase.
As far as I can tell, your last Travis run was green, right? https://travis-ci.org/angular/angular/builds/136680358

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm.

@KiaraGrouwstra
Copy link
Contributor Author

Um, I tried merging in anything newer, then rebasing everything but the original commit out again in my issue branch. I don't see that reflected here yet, but I'm not sure if that was as you'd intended it.

@tbosch
Copy link
Contributor

tbosch commented Jun 21, 2016

Somehow you got a lot of commits into the PR. You should only have one that contains the changes you would like to make...

You can try doing a:

git fetch upstream master
git checkout issue-7084
git rebase upstream/master

@googlebot
Copy link

CLAs look good, thanks!

@@ -116,6 +116,11 @@ export class RuntimeCompiler implements ComponentResolver {
var childViewPipes: CompilePipeMetadata[] =
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
Copy link
Contributor

@vicb vicb Jun 22, 2016

Choose a reason for hiding this comment

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

What about:

var childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1 || childViewDirectives.some(dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);

@KiaraGrouwstra KiaraGrouwstra force-pushed the issue-7084 branch 6 times, most recently from f832dc9 to 15fb42d Compare June 22, 2016 06:07
Fix how the compiler checks for recursive components by also considering
component descendants. Previously, it only checked if the current
component was evaluated previously. This failed in certain cases of
mutually recursive components, causing `createAsync` in tests to not
resolve.

closes [7084](angular#7084)
@KiaraGrouwstra
Copy link
Contributor Author

Thanks for the advice to both.

@vicb vicb merged commit 3d5bb23 into angular:master Jun 22, 2016
@vicb vicb removed the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Jun 22, 2016
@KiaraGrouwstra KiaraGrouwstra deleted the issue-7084 branch June 22, 2016 14:10
tbosch added a commit to tbosch/angular that referenced this pull request Jun 27, 2016
This fix prevented waiting for child components even if the cycle was only introduced via the `directives` array, i.e. without actually having a cycle. This easily causes issues for applications that have one shared list of directives for all components.

This reverts commit 3d5bb23.
@tbosch
Copy link
Contributor

tbosch commented Jun 27, 2016

Hi, I had to revert this commit, see #9647

tbosch added a commit to tbosch/angular that referenced this pull request Jun 27, 2016
This fix prevented waiting for child components even if the cycle was only introduced via the `directives` array, i.e. without actually having a cycle. This easily causes issues for applications that have one shared list of directives for all components.

This reverts commit 3d5bb23.
tbosch added a commit that referenced this pull request Jun 27, 2016
This fix prevented waiting for child components even if the cycle was only introduced via the `directives` array, i.e. without actually having a cycle. This easily causes issues for applications that have one shared list of directives for all components.

This reverts commit 3d5bb23.

Closes #9647
@tbosch
Copy link
Contributor

tbosch commented Jun 28, 2016

See #9594 for a better fix.

@KiaraGrouwstra
Copy link
Contributor Author

No problem, I'll have to admit it was hard for me to foresee all potential implications. It does make me curious though, since I hadn't really experienced issues with it yet (from monkey-patching to test).

@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 Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants