Skip to content

Commit

Permalink
fix(compiler-cli): do not error with prepocessing if component has no…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
clydin authored and zarend committed Apr 14, 2021
1 parent a63cf72 commit 1b43158
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/compiler-cli/src/ngtsc/annotations/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ export class ComponentDecoratorHandler implements
this.preanalyzeStylesCache.set(node, styles);
});
}
} else {
this.preanalyzeStylesCache.set(node, null);
}

// Wait for both the template and all styleUrl resources to resolve.
Expand Down
68 changes: 68 additions & 0 deletions packages/compiler-cli/src/ngtsc/annotations/test/component_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,74 @@ runInEachFileSystem(() => {
const {analysis} = handler.analyze(TestCmp, detected.metadata);
expect(analysis?.inlineStyles).toEqual(jasmine.arrayWithExactContents(['.xyz {}']));
});

it('should error if canPreprocess is true and async analyze is not used', async () => {
const {program, options, host} = makeProgram([
{
name: _('/node_modules/@angular/core/index.d.ts'),
contents: 'export const Component: any;',
},
{
name: _('/entry.ts'),
contents: `
import {Component} from '@angular/core';
@Component({
template: '',
styles: ['.abc {}']
}) class TestCmp {}
`
},
]);
const {reflectionHost, handler, resourceLoader} = setup(program, options, host);
resourceLoader.canPreload = true;
resourceLoader.canPreprocess = true;

const TestCmp = getDeclaration(program, _('/entry.ts'), 'TestCmp', isNamedClassDeclaration);
const detected = handler.detect(TestCmp, reflectionHost.getDecoratorsOfDeclaration(TestCmp));
if (detected === undefined) {
return fail('Failed to recognize @Component');
}

expect(() => handler.analyze(TestCmp, detected.metadata))
.toThrowError('Inline resource processing requires asynchronous preanalyze.');
});

it('should not error if component has no inline styles and canPreprocess is true', async () => {
const {program, options, host} = makeProgram([
{
name: _('/node_modules/@angular/core/index.d.ts'),
contents: 'export const Component: any;',
},
{
name: _('/entry.ts'),
contents: `
import {Component} from '@angular/core';
@Component({
template: '',
}) class TestCmp {}
`
},
]);
const {reflectionHost, handler, resourceLoader} = setup(program, options, host);
resourceLoader.canPreload = true;
resourceLoader.canPreprocess = true;
resourceLoader.preprocessInline = async function(data, context) {
fail('preprocessInline should not have been called.');
return data;
};

const TestCmp = getDeclaration(program, _('/entry.ts'), 'TestCmp', isNamedClassDeclaration);
const detected = handler.detect(TestCmp, reflectionHost.getDecoratorsOfDeclaration(TestCmp));
if (detected === undefined) {
return fail('Failed to recognize @Component');
}

await handler.preanalyze(TestCmp, detected.metadata);

expect(() => handler.analyze(TestCmp, detected.metadata)).not.toThrow();
});
});

function ivyCode(code: ErrorCode): number {
Expand Down

0 comments on commit 1b43158

Please sign in to comment.