Skip to content

Commit a5fe8b9

Browse files
clydinzarend
authored andcommitted
fix(compiler-cli): do not error with prepocessing if component has no inline styles (#41602)
The asynchronous preprocessing check was not accounting for components that did not have any inline styles. In that case, the cache did not have an entry which then allowed the asynchronous check to run and fail the compilation. The caching during the asynchronous analysis phase now handles components without inline styles. PR Close #41602
1 parent afed386 commit a5fe8b9

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

packages/compiler-cli/src/ngtsc/annotations/src/component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ export class ComponentDecoratorHandler implements
302302
this.preanalyzeStylesCache.set(node, styles);
303303
});
304304
}
305+
} else {
306+
this.preanalyzeStylesCache.set(node, null);
305307
}
306308

307309
// Wait for both the template and all styleUrl resources to resolve.

packages/compiler-cli/src/ngtsc/annotations/test/component_spec.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,74 @@ runInEachFileSystem(() => {
302302
const {analysis} = handler.analyze(TestCmp, detected.metadata);
303303
expect(analysis?.inlineStyles).toEqual(jasmine.arrayWithExactContents(['.xyz {}']));
304304
});
305+
306+
it('should error if canPreprocess is true and async analyze is not used', async () => {
307+
const {program, options, host} = makeProgram([
308+
{
309+
name: _('/node_modules/@angular/core/index.d.ts'),
310+
contents: 'export const Component: any;',
311+
},
312+
{
313+
name: _('/entry.ts'),
314+
contents: `
315+
import {Component} from '@angular/core';
316+
317+
@Component({
318+
template: '',
319+
styles: ['.abc {}']
320+
}) class TestCmp {}
321+
`
322+
},
323+
]);
324+
const {reflectionHost, handler, resourceLoader} = setup(program, options, host);
325+
resourceLoader.canPreload = true;
326+
resourceLoader.canPreprocess = true;
327+
328+
const TestCmp = getDeclaration(program, _('/entry.ts'), 'TestCmp', isNamedClassDeclaration);
329+
const detected = handler.detect(TestCmp, reflectionHost.getDecoratorsOfDeclaration(TestCmp));
330+
if (detected === undefined) {
331+
return fail('Failed to recognize @Component');
332+
}
333+
334+
expect(() => handler.analyze(TestCmp, detected.metadata))
335+
.toThrowError('Inline resource processing requires asynchronous preanalyze.');
336+
});
337+
338+
it('should not error if component has no inline styles and canPreprocess is true', async () => {
339+
const {program, options, host} = makeProgram([
340+
{
341+
name: _('/node_modules/@angular/core/index.d.ts'),
342+
contents: 'export const Component: any;',
343+
},
344+
{
345+
name: _('/entry.ts'),
346+
contents: `
347+
import {Component} from '@angular/core';
348+
349+
@Component({
350+
template: '',
351+
}) class TestCmp {}
352+
`
353+
},
354+
]);
355+
const {reflectionHost, handler, resourceLoader} = setup(program, options, host);
356+
resourceLoader.canPreload = true;
357+
resourceLoader.canPreprocess = true;
358+
resourceLoader.preprocessInline = async function(data, context) {
359+
fail('preprocessInline should not have been called.');
360+
return data;
361+
};
362+
363+
const TestCmp = getDeclaration(program, _('/entry.ts'), 'TestCmp', isNamedClassDeclaration);
364+
const detected = handler.detect(TestCmp, reflectionHost.getDecoratorsOfDeclaration(TestCmp));
365+
if (detected === undefined) {
366+
return fail('Failed to recognize @Component');
367+
}
368+
369+
await handler.preanalyze(TestCmp, detected.metadata);
370+
371+
expect(() => handler.analyze(TestCmp, detected.metadata)).not.toThrow();
372+
});
305373
});
306374

307375
function ivyCode(code: ErrorCode): number {

0 commit comments

Comments
 (0)