From 29095766e633db91aca57e5d8251dcf41dbbcd74 Mon Sep 17 00:00:00 2001 From: Yegor Jbanov Date: Thu, 30 Jul 2015 08:47:23 -0700 Subject: [PATCH] fix(bootstrap): fix expressions containing bootstrap (fixes #3309) --- .../angular2/src/core/application_static.dart | 5 ++- .../reflection_remover/rewriter.dart | 36 ++++++++++++++----- .../reflection_remover/all_tests.dart | 8 +++++ .../bootstrap_files/README.md | 5 +++ .../bootstrap_files/expected/index.dart | 19 ++++++++++ .../bootstrap_files/index.dart | 7 ++++ 6 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 modules/angular2/test/transform/reflection_remover/bootstrap_files/README.md create mode 100644 modules/angular2/test/transform/reflection_remover/bootstrap_files/expected/index.dart create mode 100644 modules/angular2/test/transform/reflection_remover/bootstrap_files/index.dart diff --git a/modules/angular2/src/core/application_static.dart b/modules/angular2/src/core/application_static.dart index d8e01d5529..2a76cf75f2 100644 --- a/modules/angular2/src/core/application_static.dart +++ b/modules/angular2/src/core/application_static.dart @@ -7,6 +7,9 @@ import 'application_common.dart'; /// /// See [commonBootstrap] for detailed documentation. Future bootstrapStatic(Type appComponentType, - [List componentInjectableBindings]) { + [List componentInjectableBindings, void initReflector()]) { + if (initReflector != null) { + initReflector(); + } return commonBootstrap(appComponentType, componentInjectableBindings); } diff --git a/modules/angular2/src/transform/reflection_remover/rewriter.dart b/modules/angular2/src/transform/reflection_remover/rewriter.dart index 4a1f6b0a51..edae3b24e4 100644 --- a/modules/angular2/src/transform/reflection_remover/rewriter.dart +++ b/modules/angular2/src/transform/reflection_remover/rewriter.dart @@ -124,9 +124,29 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { _rewriteBootstrapCallToStatic(MethodInvocation node) { if (_rewriter._writeStaticInit) { buf.write(_rewriter._code.substring(_currentIndex, node.offset)); - _writeStaticReflectorInitOnce(); + + var args = node.argumentList.arguments; + int numArgs = node.argumentList.arguments.length; + if (numArgs < 1 || numArgs > 2) { + logger.warning('`bootstrap` does not support $numArgs arguments. Found bootstrap${node.argumentList}. Transform may not succeed.'); + } + + var reflectorInit = _setupAdded + ? '' + : ', () { ${_getStaticReflectorInitBlock()} }'; + // rewrite `bootstrap(...)` to `bootstrapStatic(...)` - buf.write('bootstrapStatic${node.argumentList}'); + buf.write('bootstrapStatic('); + buf.write(args[0]); + if (numArgs == 1) { + if (reflectorInit.isNotEmpty) { + buf.write(', null'); + } + } else { + buf.write(', ${args[1]}'); + } + buf.write(reflectorInit); + buf.write(')'); } else { // leave it as is buf.write(_rewriter._code.substring(_currentIndex, node.end)); @@ -134,11 +154,8 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { _currentIndex = node.end; } - _writeStaticReflectorInitOnce() { - if (!_setupAdded) { - buf.write(_rewriter._codegen.codegenSetupReflectionCall()); - _setupAdded = true; - } + String _getStaticReflectorInitBlock() { + return _rewriter._codegen.codegenSetupReflectionCall(); } _rewriteReflectionCapabilitiesImport(ImportDirective node) { @@ -162,8 +179,9 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor { node = node.parent; } buf.write(_rewriter._code.substring(_currentIndex, node.offset)); - if (_rewriter._writeStaticInit) { - _writeStaticReflectorInitOnce(); + if (_rewriter._writeStaticInit && !_setupAdded) { + buf.write(_getStaticReflectorInitBlock()); + _setupAdded = true; } switch (_rewriter._mirrorMode) { case MirrorMode.debug: diff --git a/modules/angular2/test/transform/reflection_remover/all_tests.dart b/modules/angular2/test/transform/reflection_remover/all_tests.dart index 46b59b535d..e1b2c7ad57 100644 --- a/modules/angular2/test/transform/reflection_remover/all_tests.dart +++ b/modules/angular2/test/transform/reflection_remover/all_tests.dart @@ -10,6 +10,7 @@ import 'reflection_remover_files/expected/index.dart' as expected; import 'debug_mirrors_files/expected/index.dart' as debug_mirrors; import 'log_mirrors_files/expected/index.dart' as log_mirrors; import 'verbose_files/expected/index.dart' as verbose_mirrors; +import 'bootstrap_files/expected/index.dart' as bootstrap_expected; import '../common/read_file.dart'; main() => allTests(); @@ -17,6 +18,7 @@ main() => allTests(); void allTests() { var codegen = new Codegen('web/index.dart', ['web/index.ng_deps.dart']); var code = readFile('reflection_remover/index.dart').replaceAll('\r\n', '\n'); + var bootstrapCode = readFile('reflection_remover/bootstrap_files/index.dart').replaceAll('\r\n', '\n'); it('should remove uses of mirrors & ' 'insert calls to generated code by default.', () { @@ -45,4 +47,10 @@ void allTests() { .rewrite(parseCompilationUnit(code)); expect(output).toEqual(log_mirrors.code); }); + + it('should rewrite bootstrap.', () { + var output = new Rewriter(bootstrapCode, codegen, writeStaticInit: true) + .rewrite(parseCompilationUnit(bootstrapCode)); + expect(output).toEqual(bootstrap_expected.code); + }); } diff --git a/modules/angular2/test/transform/reflection_remover/bootstrap_files/README.md b/modules/angular2/test/transform/reflection_remover/bootstrap_files/README.md new file mode 100644 index 0000000000..6a55dc7bf5 --- /dev/null +++ b/modules/angular2/test/transform/reflection_remover/bootstrap_files/README.md @@ -0,0 +1,5 @@ +Tests that the reflection removal step: + 1. Comments out reflective `bootstrap.dart` import + 1. Adds `bootstrap_static.dart` import + 1. Adds the call to `initReflector` + 1. Handles bootstrap return values properly diff --git a/modules/angular2/test/transform/reflection_remover/bootstrap_files/expected/index.dart b/modules/angular2/test/transform/reflection_remover/bootstrap_files/expected/index.dart new file mode 100644 index 0000000000..54ac022aa4 --- /dev/null +++ b/modules/angular2/test/transform/reflection_remover/bootstrap_files/expected/index.dart @@ -0,0 +1,19 @@ +library angular2.test.transform.reflection_remover.reflection_remover_files; + +// This file is intentionally formatted as a string to avoid having the +// automatic transformer prettify it. +// +// This file represents transformed user code. Because this code will be +// linked to output by a source map, we cannot change line numbers from the +// original code and we therefore add our generated code on the same line as +// those we are removing. + +var code = """ +library web_foo; + +import 'package:angular2/bootstrap_static.dart';import 'index.ng_deps.dart' as ngStaticInit0; + +void main() async { + var appRef = await bootstrapStatic(MyComponent, null, () { ngStaticInit0.initReflector(); }); +} +"""; diff --git a/modules/angular2/test/transform/reflection_remover/bootstrap_files/index.dart b/modules/angular2/test/transform/reflection_remover/bootstrap_files/index.dart new file mode 100644 index 0000000000..091b5e8466 --- /dev/null +++ b/modules/angular2/test/transform/reflection_remover/bootstrap_files/index.dart @@ -0,0 +1,7 @@ +library web_foo; + +import 'package:angular2/bootstrap.dart'; + +void main() async { + var appRef = await bootstrap(MyComponent); +}