Skip to content

Commit d037c08

Browse files
committed
fix(transformer): Don't hang on bad urls and log better errors
closes angular#2605
1 parent 9c76850 commit d037c08

File tree

5 files changed

+99
-4
lines changed

5 files changed

+99
-4
lines changed

modules/angular2/src/transform/common/xhr_impl.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ class XhrImpl implements XHR {
1616
Future<String> get(String url) async {
1717
var assetId = uriToAssetId(_entryPoint, url, logger, null /* span */,
1818
errorOnAbsolute: false);
19+
if (assetId == null) {
20+
logger.error(
21+
'Uri $url not supported from $_entryPoint, could not build AssetId');
22+
return null;
23+
}
1924
var templateExists = await _reader.hasInput(assetId);
2025
if (!templateExists) {
21-
logger.error('Could not read template at uri $url from $_entryPoint');
26+
logger.error('Could not read asset at uri $url from $_entryPoint');
2227
return null;
2328
}
2429
return await _reader.readAsString(assetId);

modules/angular2/src/transform/directive_processor/visitors.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
library angular2.transform.directive_processor.visitors;
22

3+
import 'dart:async';
34
import 'package:analyzer/analyzer.dart';
45
import 'package:analyzer/src/generated/java_core.dart';
56
import 'package:angular2/src/render/xhr.dart' show XHR;
@@ -263,7 +264,7 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
263264
var url = node.expression.accept(_evaluator);
264265
if (url is String) {
265266
writer.print("template: r'''");
266-
writer.asyncPrint(_xhr.get(url));
267+
writer.asyncPrint(_readOrEmptyString(url));
267268
writer.print("'''");
268269
return null;
269270
} else {
@@ -276,7 +277,7 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
276277
for (var url in urls) {
277278
if (url is String) {
278279
writer.print("r'''");
279-
writer.asyncPrint(_xhr.get(url));
280+
writer.asyncPrint(_readOrEmptyString(url));
280281
writer.print("''', ");
281282
} else {
282283
logger.warning('style url is not a String ${url}');
@@ -287,4 +288,14 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
287288
}
288289
return super.visitNamedExpression(node);
289290
}
291+
292+
/// Attempts to read the content from {@link url}, if it returns null then
293+
/// just return the empty string.
294+
Future<String> _readOrEmptyString(String url) async {
295+
var content = await _xhr.get(url);
296+
if (content == null) {
297+
content = '';
298+
}
299+
return content;
300+
}
290301
}

modules/angular2/test/transform/directive_processor/all_tests.dart

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import 'package:barback/barback.dart';
44
import 'package:angular2/src/transform/directive_processor/rewriter.dart';
55
import 'package:angular2/src/transform/common/annotation_matcher.dart';
66
import 'package:angular2/src/transform/common/asset_reader.dart';
7+
import 'package:angular2/src/transform/common/logging.dart' as log;
8+
import 'package:code_transformers/messages/build_logger.dart';
79
import 'package:dart_style/dart_style.dart';
810
import 'package:guinness/guinness.dart';
911
import 'package:path/path.dart' as path;
@@ -67,12 +69,29 @@ void allTests() {
6769

6870
_testNgDeps('should not include superclasses in `interfaces`.',
6971
'superclass_files/soup.dart');
72+
73+
_testNgDeps(
74+
'should not throw/hang on invalid urls', 'invalid_url_files/hello.dart',
75+
expectedLogs: [
76+
'ERROR: Uri /bad/absolute/url.html not supported from angular2|test/'
77+
'transform/directive_processor/invalid_url_files/hello.dart, could not '
78+
'build AssetId',
79+
'ERROR: Could not read asset at uri package:invalid/package.css from '
80+
'angular2|test/transform/directive_processor/invalid_url_files/'
81+
'hello.dart',
82+
'ERROR: Could not read asset at uri bad_relative_url.css from angular2|'
83+
'test/transform/directive_processor/invalid_url_files/hello.dart'
84+
]);
7085
}
7186

7287
void _testNgDeps(String name, String inputPath,
7388
{List<AnnotationDescriptor> customDescriptors: const [], AssetId assetId,
74-
AssetReader reader}) {
89+
AssetReader reader, List<String> expectedLogs}) {
7590
it(name, () async {
91+
if (expectedLogs != null) {
92+
log.setLogger(new RecordingLogger());
93+
}
94+
7695
var inputId = _assetIdForPath(inputPath);
7796
if (reader == null) {
7897
reader = new TestAssetReader();
@@ -93,8 +112,35 @@ void _testNgDeps(String name, String inputPath,
93112
expect(formatter.format(output))
94113
.toEqual((await reader.readAsString(expectedId)).replaceAll('\r\n', '\n'));
95114
}
115+
116+
if (expectedLogs != null) {
117+
expect((log.logger as RecordingLogger).logs, expectedLogs);
118+
}
96119
});
97120
}
98121

99122
AssetId _assetIdForPath(String path) =>
100123
new AssetId('angular2', 'test/transform/directive_processor/$path');
124+
125+
class RecordingLogger implements BuildLogger {
126+
@override
127+
final String detailsUri = '';
128+
@override
129+
final bool convertErrorsToWarnings = false;
130+
131+
List<String> logs = [];
132+
133+
void _record(prefix, msg) => logs.add('$prefix: $msg');
134+
135+
void info(msg, {AssetId asset, SourceSpan span}) => _record('INFO', msg);
136+
137+
void fine(msg, {AssetId asset, SourceSpan span}) => _record('FINE', msg);
138+
139+
void warning(msg, {AssetId asset, SourceSpan span}) => _record('WARN', msg);
140+
141+
void error(msg, {AssetId asset, SourceSpan span}) => _record('ERROR', msg);
142+
143+
Future writeOutput() => throw new UnimplementedError();
144+
Future addLogFilesFromAsset(AssetId id, [int nextNumber = 1]) =>
145+
throw new UnimplementedError();
146+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
library test.transform.directive_processor.url_expression_files.hello.ng_deps.dart;
2+
3+
import 'hello.dart';
4+
import 'package:angular2/angular2.dart'
5+
show bootstrap, Component, Directive, View, NgElement;
6+
7+
var _visited = false;
8+
void initReflector(reflector) {
9+
if (_visited) return;
10+
_visited = true;
11+
reflector
12+
..registerType(HelloCmp, {
13+
'factory': () => new HelloCmp(),
14+
'parameters': const [],
15+
'annotations': const [
16+
const Component(selector: 'hello-app'),
17+
const View(template: r'''''', styles: const [r'''''', r'''''',])
18+
]
19+
});
20+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
library test.transform.directive_processor.url_expression_files.hello;
2+
3+
import 'package:angular2/angular2.dart'
4+
show bootstrap, Component, Directive, View, NgElement;
5+
6+
@Component(selector: 'hello-app')
7+
@View(
8+
templateUrl: '/bad/absolute/url.html',
9+
styleUrls: const [
10+
'package:invalid/package.css',
11+
'bad_relative_url.css'
12+
])
13+
class HelloCmp {}

0 commit comments

Comments
 (0)