Skip to content

Commit 05d96dc

Browse files
tboschvicb
authored andcommitted
feat(core): allow to pass in aot summaries also to TestBed.configureTestingModule
Also adds caching for summaries. Closes angular#19817.
1 parent b489259 commit 05d96dc

File tree

3 files changed

+68
-30
lines changed

3 files changed

+68
-30
lines changed

packages/compiler/src/jit/compiler.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class JitCompiler {
4242
private _compiledDirectiveWrapperCache = new Map<Type, Type>();
4343
private _compiledNgModuleCache = new Map<Type, object>();
4444
private _sharedStylesheetCount = 0;
45+
private _addedAotSummaries = new Set<() => any[]>();
4546

4647
constructor(
4748
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
@@ -74,10 +75,25 @@ export class JitCompiler {
7475

7576
loadAotSummaries(summaries: () => any[]) {
7677
this.clearCache();
77-
flattenSummaries(summaries).forEach((summary) => {
78-
this._summaryResolver.addSummary(
79-
{symbol: summary.type.reference, metadata: null, type: summary});
80-
});
78+
this._addAotSummaries(summaries);
79+
}
80+
81+
private _addAotSummaries(fn: () => any[]) {
82+
if (this._addedAotSummaries.has(fn)) {
83+
return;
84+
}
85+
this._addedAotSummaries.add(fn);
86+
const summaries = fn();
87+
for (let i = 0; i < summaries.length; i++) {
88+
const entry = summaries[i];
89+
if (typeof entry === 'function') {
90+
this._addAotSummaries(entry);
91+
} else {
92+
const summary = entry as CompileTypeSummary;
93+
this._summaryResolver.addSummary(
94+
{symbol: summary.type.reference, metadata: null, type: summary})
95+
}
96+
}
8197
}
8298

8399
hasAotSummary(ref: Type) { return !!this._summaryResolver.resolveSummary(ref); }
@@ -200,6 +216,7 @@ export class JitCompiler {
200216
}
201217

202218
clearCache(): void {
219+
// Note: don't clear the _addedAotSummaries, as they don't change!
203220
this._metadataResolver.clearCache();
204221
this._compiledTemplateCache.clear();
205222
this._compiledHostTemplateCache.clear();
@@ -335,25 +352,6 @@ function assertComponent(meta: CompileDirectiveMetadata) {
335352
}
336353
}
337354

338-
function flattenSummaries(
339-
fn: () => any[], out: CompileTypeSummary[] = [],
340-
seen = new Set<() => any[]>()): CompileTypeSummary[] {
341-
if (seen.has(fn)) {
342-
return out;
343-
}
344-
seen.add(fn);
345-
const summaries = fn();
346-
for (let i = 0; i < summaries.length; i++) {
347-
const entry = summaries[i];
348-
if (typeof entry === 'function') {
349-
flattenSummaries(entry, out, seen);
350-
} else {
351-
out.push(entry);
352-
}
353-
}
354-
return out;
355-
}
356-
357355
function createOutputContext(): OutputContext {
358356
const importExpr = (symbol: any) =>
359357
ir.importExpr({name: identifierName(symbol), moduleName: null, runtime: symbol});

packages/core/test/linker/jit_summaries_integration_spec.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {TestBed, async, getTestBed} from '@angular/core/testing';
1515
export function main() {
1616
describe('Jit Summaries', () => {
1717
let instances: Map<any, Base>;
18+
let summaries: () => any[];
1819

1920
class SomeDep {}
2021

@@ -69,7 +70,7 @@ export function main() {
6970
TestBed.configureCompiler({providers: [{provide: ResourceLoader, useValue: resourceLoader}]});
7071
TestBed.configureTestingModule({imports: [SomeModule], providers: [SomeDep]});
7172

72-
TestBed.compileComponents().then(() => {
73+
let summariesPromise = TestBed.compileComponents().then(() => {
7374
const metadataResolver = TestBed.get(CompileMetadataResolver) as CompileMetadataResolver;
7475
const summaries = [
7576
metadataResolver.getNgModuleSummary(SomeModule),
@@ -83,10 +84,12 @@ export function main() {
8384
metadataResolver.getInjectableSummary(SomeService)
8485
];
8586
clearMetadata();
86-
resetTestEnvironmentWithSummaries(() => summaries);
87+
TestBed.resetTestingModule();
88+
return () => summaries;
8789
});
8890

8991
resourceLoader.flush();
92+
return summariesPromise;
9093
}
9194

9295
function setMetadata(resourceLoader: MockResourceLoader) {
@@ -123,12 +126,14 @@ export function main() {
123126

124127
beforeEach(async(() => {
125128
instances = new Map<any, any>();
126-
createSummaries();
129+
createSummaries().then(s => summaries = s);
127130
}));
128131

129132
afterEach(() => { resetTestEnvironmentWithSummaries(); });
130133

131134
it('should use directive metadata from summaries', () => {
135+
resetTestEnvironmentWithSummaries(summaries);
136+
132137
@Component({template: '<div someDir></div>'})
133138
class TestComp {
134139
}
@@ -140,6 +145,8 @@ export function main() {
140145
});
141146

142147
it('should use pipe metadata from summaries', () => {
148+
resetTestEnvironmentWithSummaries(summaries);
149+
143150
@Component({template: '{{1 | somePipe}}'})
144151
class TestComp {
145152
}
@@ -150,6 +157,8 @@ export function main() {
150157
});
151158

152159
it('should use Service metadata from summaries', () => {
160+
resetTestEnvironmentWithSummaries(summaries);
161+
153162
TestBed.configureTestingModule({
154163
providers: [SomeService, SomeDep],
155164
});
@@ -158,6 +167,8 @@ export function main() {
158167
});
159168

160169
it('should use NgModule metadata from summaries', () => {
170+
resetTestEnvironmentWithSummaries(summaries);
171+
161172
TestBed
162173
.configureTestingModule(
163174
{providers: [SomeDep], declarations: [TestComp3], imports: [SomeModule]})
@@ -170,12 +181,16 @@ export function main() {
170181
});
171182

172183
it('should allow to create private components from imported NgModule summaries', () => {
184+
resetTestEnvironmentWithSummaries(summaries);
185+
173186
TestBed.configureTestingModule({providers: [SomeDep], imports: [SomeModule]})
174187
.createComponent(SomePrivateComponent);
175188
expectInstanceCreated(SomePrivateComponent);
176189
});
177190

178191
it('should throw when trying to mock a type with a summary', () => {
192+
resetTestEnvironmentWithSummaries(summaries);
193+
179194
TestBed.resetTestingModule();
180195
expect(() => TestBed.overrideComponent(SomePrivateComponent, {add: {}}).compileComponents())
181196
.toThrowError(
@@ -190,5 +205,22 @@ export function main() {
190205
expect(() => TestBed.overrideModule(SomeModule, {add: {}}).compileComponents())
191206
.toThrowError('SomeModule was AOT compiled, so its metadata cannot be changed.');
192207
});
208+
209+
it('should allow to add summaries via configureTestingModule', () => {
210+
resetTestEnvironmentWithSummaries();
211+
212+
@Component({template: '<div someDir></div>'})
213+
class TestComp {
214+
}
215+
216+
TestBed
217+
.configureTestingModule({
218+
providers: [SomeDep],
219+
declarations: [TestComp, SomeDirective],
220+
aotSummaries: summaries
221+
})
222+
.createComponent(TestComp);
223+
expectInstanceCreated(SomeDirective);
224+
});
193225
});
194226
}

packages/core/testing/src/test_bed.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type TestModuleMetadata = {
4545
declarations?: any[],
4646
imports?: any[],
4747
schemas?: Array<SchemaMetadata|any[]>,
48+
aotSummaries?: () => any[],
4849
};
4950

5051
/**
@@ -205,7 +206,8 @@ export class TestBed implements Injector {
205206
private _schemas: Array<SchemaMetadata|any[]> = [];
206207
private _activeFixtures: ComponentFixture<any>[] = [];
207208

208-
private _aotSummaries: () => any[] = () => [];
209+
private _testEnvAotSummaries: () => any[] = () => [];
210+
private _aotSummaries: Array<() => any[]> = [];
209211

210212
platform: PlatformRef = null !;
211213

@@ -232,7 +234,7 @@ export class TestBed implements Injector {
232234
this.platform = platform;
233235
this.ngModule = ngModule;
234236
if (aotSummaries) {
235-
this._aotSummaries = aotSummaries;
237+
this._testEnvAotSummaries = aotSummaries;
236238
}
237239
}
238240

@@ -245,11 +247,12 @@ export class TestBed implements Injector {
245247
this.resetTestingModule();
246248
this.platform = null !;
247249
this.ngModule = null !;
248-
this._aotSummaries = () => [];
250+
this._testEnvAotSummaries = () => [];
249251
}
250252

251253
resetTestingModule() {
252254
clearProviderOverrides();
255+
this._aotSummaries = [];
253256
this._compiler = null !;
254257
this._moduleOverrides = [];
255258
this._componentOverrides = [];
@@ -293,6 +296,9 @@ export class TestBed implements Injector {
293296
if (moduleDef.schemas) {
294297
this._schemas.push(...moduleDef.schemas);
295298
}
299+
if (moduleDef.aotSummaries) {
300+
this._aotSummaries.push(moduleDef.aotSummaries);
301+
}
296302
}
297303

298304
compileComponents(): Promise<any> {
@@ -350,7 +356,9 @@ export class TestBed implements Injector {
350356
const compilerFactory: TestingCompilerFactory =
351357
this.platform.injector.get(TestingCompilerFactory);
352358
this._compiler = compilerFactory.createTestingCompiler(this._compilerOptions);
353-
this._compiler.loadAotSummaries(this._aotSummaries);
359+
for (const summary of [this._testEnvAotSummaries, ...this._aotSummaries]) {
360+
this._compiler.loadAotSummaries(summary);
361+
}
354362
this._moduleOverrides.forEach((entry) => this._compiler.overrideModule(entry[0], entry[1]));
355363
this._componentOverrides.forEach(
356364
(entry) => this._compiler.overrideComponent(entry[0], entry[1]));

0 commit comments

Comments
 (0)