Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/render3/jit/directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function getStandaloneDefFunctions(type: Type<any>, imports: Type<any>[]): {
// Standalone components are always able to self-reference, so include the component's own
// definition in its `directiveDefs`.
cachedDirectiveDefs = [getComponentDef(type)!];
const seen = new Set<Type<unknown>>();
const seen = new Set<Type<unknown>>([type]);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Note that we pre-include the current def in the cachedDirectiveDefs, but we never add it to the seen which is why it never gets deduped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great catch! 👍


for (const rawDep of imports) {
ngDevMode && verifyStandaloneImport(rawDep, type);
Expand Down
66 changes: 64 additions & 2 deletions packages/core/test/acceptance/component_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT} from '@angular/common';
import {ApplicationRef, Component, ComponentRef, createComponent, createEnvironmentInjector, Directive, ElementRef, EmbeddedViewRef, EnvironmentInjector, inject, Injectable, InjectionToken, Injector, Input, NgModule, OnDestroy, reflectComponentType, Renderer2, Type, ViewChild, ViewContainerRef, ViewEncapsulation, ɵsetDocument} from '@angular/core';
import {DOCUMENT, NgIf} from '@angular/common';
import {ApplicationRef, Component, ComponentRef, createComponent, createEnvironmentInjector, Directive, ElementRef, EmbeddedViewRef, EnvironmentInjector, forwardRef, inject, Injectable, InjectionToken, Injector, Input, NgModule, OnDestroy, reflectComponentType, Renderer2, Type, ViewChild, ViewContainerRef, ViewEncapsulation, ɵsetDocument} from '@angular/core';
import {stringifyForError} from '@angular/core/src/render3/util/stringify_utils';
import {TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
Expand Down Expand Up @@ -400,6 +400,68 @@ describe('component', () => {
.toThrowError(
/NG0300: Multiple components match node with tagname comp: CompA and CompB/);
});

it('should not throw if a standalone component imports itself', () => {
@Component({
selector: 'comp',
template: '<comp *ngIf="recurse"/>hello',
standalone: true,
imports: [Comp, NgIf]
})
class Comp {
@Input() recurse = false;
}

@Component({
template: '<comp [recurse]="true"/>',
standalone: true,
imports: [Comp],
})
class App {
}

let textContent = '';

expect(() => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
textContent = fixture.nativeElement.textContent.trim();
}).not.toThrow();

// Ensure that the component actually rendered.
expect(textContent).toBe('hellohello');
});

it('should not throw if a standalone component imports itself using a forwardRef', () => {
@Component({
selector: 'comp',
template: '<comp *ngIf="recurse"/>hello',
standalone: true,
imports: [forwardRef(() => Comp), NgIf]
})
class Comp {
@Input() recurse = false;
}

@Component({
template: '<comp [recurse]="true"/>',
standalone: true,
imports: [Comp],
})
class App {
}

let textContent = '';

expect(() => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
textContent = fixture.nativeElement.textContent.trim();
}).not.toThrow();

// Ensure that the component actually rendered.
expect(textContent).toBe('hellohello');
});
});

it('should use a new ngcontent attribute for child elements created w/ Renderer2', () => {
Expand Down