Skip to content

Commit 96606b3

Browse files
alan-agius4vikerman
authored andcommitted
fix(@ngtools/webpack): replace resources should effect only class decorators (#12503)
At the moment we are processing all property assignments in object literals irrespective if they are in a decorator or not. With this change we will process only property assignments found under in a component decorator. Fixes #12488, Fixes #6007, Fixes: #6498 and Fixes: #8295
1 parent bd4dc38 commit 96606b3

File tree

6 files changed

+512
-127
lines changed

6 files changed

+512
-127
lines changed

packages/ngtools/webpack/src/angular_compiler_plugin.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ export class AngularCompilerPlugin {
817817

818818
if (this._JitMode) {
819819
// Replace resources in JIT.
820-
this._transformers.push(replaceResources(isAppPath));
820+
this._transformers.push(replaceResources(isAppPath, getTypeChecker));
821821
} else {
822822
// Remove unneeded angular decorators.
823823
this._transformers.push(removeDecorators(isAppPath, getTypeChecker));
@@ -1013,9 +1013,7 @@ export class AngularCompilerPlugin {
10131013
.filter(x => x);
10141014

10151015
const resourceImports = findResources(sourceFile)
1016-
.map((resourceReplacement) => resourceReplacement.resourcePaths)
1017-
.reduce((prev, curr) => prev.concat(curr), [])
1018-
.map((resourcePath) => resolve(dirname(resolvedFileName), normalize(resourcePath)));
1016+
.map(resourcePath => resolve(dirname(resolvedFileName), normalize(resourcePath)));
10191017

10201018
// These paths are meant to be used by the loader so we must denormalize them.
10211019
const uniqueDependencies = new Set([
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import * as ts from 'typescript';
9+
import { collectDeepNodes } from './ast_helpers';
10+
import { getResourceUrl } from './replace_resources';
11+
12+
export function findResources(sourceFile: ts.SourceFile): string[] {
13+
const resources: string[] = [];
14+
const decorators = collectDeepNodes<ts.Decorator>(sourceFile, ts.SyntaxKind.Decorator);
15+
16+
for (const node of decorators) {
17+
if (!ts.isCallExpression(node.expression)) {
18+
continue;
19+
}
20+
21+
const decoratorFactory = node.expression;
22+
const args = decoratorFactory.arguments;
23+
if (args.length !== 1 || !ts.isObjectLiteralExpression(args[0])) {
24+
// Unsupported component metadata
25+
continue;
26+
}
27+
28+
ts.visitNodes(
29+
(args[0] as ts.ObjectLiteralExpression).properties,
30+
(node: ts.ObjectLiteralElementLike) => {
31+
if (!ts.isPropertyAssignment(node) || ts.isComputedPropertyName(node.name)) {
32+
return node;
33+
}
34+
35+
const name = node.name.text;
36+
switch (name) {
37+
case 'templateUrl':
38+
const url = getResourceUrl(node.initializer);
39+
40+
if (url) {
41+
resources.push(url);
42+
}
43+
break;
44+
45+
case 'styleUrls':
46+
if (!ts.isArrayLiteralExpression(node.initializer)) {
47+
return node;
48+
}
49+
50+
ts.visitNodes(node.initializer.elements, (node: ts.Expression) => {
51+
const url = getResourceUrl(node);
52+
53+
if (url) {
54+
resources.push(url);
55+
}
56+
57+
return node;
58+
});
59+
break;
60+
}
61+
62+
return node;
63+
},
64+
);
65+
}
66+
67+
return resources;
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { tags } from '@angular-devkit/core'; // tslint:disable-line:no-implicit-dependencies
9+
import * as ts from 'typescript';
10+
import { findResources } from './find_resources';
11+
12+
13+
describe('@ngtools/webpack transformers', () => {
14+
describe('find_resources', () => {
15+
it('should return resources', () => {
16+
const input = tags.stripIndent`
17+
import { Component } from '@angular/core';
18+
19+
@Component({
20+
selector: 'app-root',
21+
templateUrl: './app.component.html',
22+
styleUrls: ['./app.component.css', './app.component.2.css']
23+
})
24+
export class AppComponent {
25+
title = 'app';
26+
}
27+
`;
28+
29+
const result = findResources(ts.createSourceFile('temp.ts', input, ts.ScriptTarget.ES2015));
30+
expect(result).toEqual([
31+
'./app.component.html',
32+
'./app.component.css',
33+
'./app.component.2.css',
34+
]);
35+
});
36+
37+
it('should not return resources if they are not in decorator', () => {
38+
const input = tags.stripIndent`
39+
const foo = {
40+
templateUrl: './app.component.html',
41+
styleUrls: ['./app.component.css', './app.component.2.css']
42+
}
43+
`;
44+
45+
const result = findResources(ts.createSourceFile('temp.ts', input, ts.ScriptTarget.ES2015));
46+
expect(result).toEqual([]);
47+
});
48+
});
49+
});

packages/ngtools/webpack/src/transformers/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export * from './export_lazy_module_map';
1717
export * from './register_locale_data';
1818
export * from './replace_resources';
1919
export * from './remove_decorators';
20+
export * from './find_resources';

0 commit comments

Comments
 (0)