OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
6 | 6 |
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
9 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 9 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 | 106 |
107 /// The current function body being compiled. | 107 /// The current function body being compiled. |
108 FunctionBody _currentFunction; | 108 FunctionBody _currentFunction; |
109 | 109 |
110 /// Helper class for emitting elements in the proper order to allow | 110 /// Helper class for emitting elements in the proper order to allow |
111 /// JS to load the module. | 111 /// JS to load the module. |
112 ElementLoader _loader; | 112 ElementLoader _loader; |
113 | 113 |
114 BuildUnit _buildUnit; | 114 BuildUnit _buildUnit; |
115 | 115 |
116 String _buildRoot; | |
117 | |
116 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) | 118 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
117 : context = c, | 119 : context = c, |
118 types = c.typeProvider, | 120 types = c.typeProvider, |
119 _asyncStreamIterator = | 121 _asyncStreamIterator = |
120 _getLibrary(c, 'dart:async').getType('StreamIterator').type, | 122 _getLibrary(c, 'dart:async').getType('StreamIterator').type, |
121 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), | 123 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), |
122 dartCoreLibrary = _getLibrary(c, 'dart:core'), | 124 dartCoreLibrary = _getLibrary(c, 'dart:core'), |
123 dartJSLibrary = _getLibrary(c, 'dart:js'); | 125 dartJSLibrary = _getLibrary(c, 'dart:js'); |
124 | 126 |
125 LibraryElement get currentLibrary => _loader.currentElement.library; | 127 LibraryElement get currentLibrary => _loader.currentElement.library; |
126 | 128 |
127 /// The main entry point to JavaScript code generation. | 129 /// The main entry point to JavaScript code generation. |
128 /// | 130 /// |
129 /// Takes the metadata for the build unit, as well as resolved trees and | 131 /// Takes the metadata for the build unit, as well as resolved trees and |
130 /// errors, and computes the output module code and optionally the source map. | 132 /// errors, and computes the output module code and optionally the source map. |
131 JSModuleFile compile(BuildUnit unit, List<CompilationUnit> compilationUnits, | 133 JSModuleFile compile(BuildUnit unit, List<CompilationUnit> compilationUnits, |
132 List<String> errors) { | 134 List<String> errors) { |
133 _buildUnit = unit; | 135 _buildUnit = unit; |
136 _buildRoot = _buildUnit.buildRoot; | |
137 if (!_buildRoot.endsWith('/')) { | |
Paul Berry
2016/04/28 15:49:30
AFAICT, buildRoot uses OS conventions, this won't
vsm
2016/04/28 21:18:04
Hmm, buildRoot might not actually be a native file
| |
138 _buildRoot = '$_buildRoot/'; | |
139 } | |
134 | 140 |
135 var jsTree = _emitModule(compilationUnits); | 141 var jsTree = _emitModule(compilationUnits); |
136 var codeAndSourceMap = _writeJSText(unit, jsTree); | 142 var codeAndSourceMap = _writeJSText(unit, jsTree); |
137 | 143 |
138 List<int> summary; | 144 List<int> summary; |
139 if (options.summarizeApi) { | 145 if (options.summarizeApi) { |
140 var assembler = new PackageBundleAssembler(); | 146 var assembler = new PackageBundleAssembler(); |
141 compilationUnits | 147 compilationUnits |
142 .map((u) => u.element.library) | 148 .map((u) => u.element.library) |
143 .toSet() | 149 .toSet() |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 compilationUnits = CoercionReifier.reify(compilationUnits); | 189 compilationUnits = CoercionReifier.reify(compilationUnits); |
184 | 190 |
185 // Initialize our library variables. | 191 // Initialize our library variables. |
186 var items = <JS.ModuleItem>[]; | 192 var items = <JS.ModuleItem>[]; |
187 for (var unit in compilationUnits) { | 193 for (var unit in compilationUnits) { |
188 var library = unit.element.library; | 194 var library = unit.element.library; |
189 if (unit.element != library.definingCompilationUnit) continue; | 195 if (unit.element != library.definingCompilationUnit) continue; |
190 | 196 |
191 var libraryTemp = _isDartRuntime(library) | 197 var libraryTemp = _isDartRuntime(library) |
192 ? _runtimeLibVar | 198 ? _runtimeLibVar |
193 : new JS.TemporaryId(jsLibraryName(library)); | 199 : new JS.TemporaryId(jsLibraryName(_buildRoot, library)); |
194 _libraries[library] = libraryTemp; | 200 _libraries[library] = libraryTemp; |
195 items.add(new JS.ExportDeclaration( | 201 items.add(new JS.ExportDeclaration( |
196 js.call('const # = Object.create(null)', [libraryTemp]))); | 202 js.call('const # = Object.create(null)', [libraryTemp]))); |
197 | 203 |
198 // dart:_runtime has a magic module that holds extenstion method symbols. | 204 // dart:_runtime has a magic module that holds extenstion method symbols. |
199 // TODO(jmesserly): find a cleaner design for this. | 205 // TODO(jmesserly): find a cleaner design for this. |
200 if (_isDartRuntime(library)) { | 206 if (_isDartRuntime(library)) { |
201 items.add(new JS.ExportDeclaration( | 207 items.add(new JS.ExportDeclaration( |
202 js.call('const # = Object.create(null)', [_dartxVar]))); | 208 js.call('const # = Object.create(null)', [_dartxVar]))); |
203 } | 209 } |
(...skipping 3549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3753 bool _externalOrNative(node) => | 3759 bool _externalOrNative(node) => |
3754 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3760 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
3755 | 3761 |
3756 FunctionBody _functionBody(node) => | 3762 FunctionBody _functionBody(node) => |
3757 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 3763 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
3758 | 3764 |
3759 /// Returns the canonical name to refer to the Dart library. | 3765 /// Returns the canonical name to refer to the Dart library. |
3760 JS.Identifier emitLibraryName(LibraryElement library) { | 3766 JS.Identifier emitLibraryName(LibraryElement library) { |
3761 // It's either one of the libraries in this module, or it's an import. | 3767 // It's either one of the libraries in this module, or it's an import. |
3762 return _libraries[library] ?? | 3768 return _libraries[library] ?? |
3763 _imports.putIfAbsent( | 3769 _imports.putIfAbsent(library, |
3764 library, () => new JS.TemporaryId(jsLibraryName(library))); | 3770 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library))); |
3765 } | 3771 } |
3766 | 3772 |
3767 JS.Node annotate(JS.Node node, AstNode original, [Element element]) { | 3773 JS.Node annotate(JS.Node node, AstNode original, [Element element]) { |
3768 if (options.closure && element != null) { | 3774 if (options.closure && element != null) { |
3769 node = node.withClosureAnnotation(closureAnnotationFor( | 3775 node = node.withClosureAnnotation(closureAnnotationFor( |
3770 node, original, element, namedArgumentTemp.name)); | 3776 node, original, element, namedArgumentTemp.name)); |
3771 } | 3777 } |
3772 return node..sourceInformation = original; | 3778 return node..sourceInformation = original; |
3773 } | 3779 } |
3774 | 3780 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3830 // TODO(leafp): The above only handles the case where the return type | 3836 // TODO(leafp): The above only handles the case where the return type |
3831 // is exactly Future/Stream/Iterable. Handle the subtype case. | 3837 // is exactly Future/Stream/Iterable. Handle the subtype case. |
3832 return DynamicTypeImpl.instance; | 3838 return DynamicTypeImpl.instance; |
3833 } | 3839 } |
3834 } | 3840 } |
3835 } | 3841 } |
3836 | 3842 |
3837 /// Choose a canonical name from the library element. | 3843 /// Choose a canonical name from the library element. |
3838 /// This never uses the library's name (the identifier in the `library` | 3844 /// This never uses the library's name (the identifier in the `library` |
3839 /// declaration) as it doesn't have any meaningful rules enforced. | 3845 /// declaration) as it doesn't have any meaningful rules enforced. |
3840 String jsLibraryName(LibraryElement library) { | 3846 String jsLibraryName(String buildRoot, LibraryElement library) { |
3841 return pathToJSIdentifier(library.source.uri.pathSegments.last); | 3847 var uri = library.source.uri; |
3848 if (uri.scheme == 'dart') { | |
3849 return uri.path; | |
3850 } | |
3851 // TODO(vsm): This is not necessarily unique if '__' appears in a file name. | |
3852 var separator = '__'; | |
3853 String qualifiedPath; | |
3854 if (uri.scheme == 'package') { | |
3855 // Strip the package name. | |
3856 // TODO(vsm): This is not unique if an escaped '/'appears in a filename. | |
3857 // E.g., "foo/bar.dart" and "foo$47bar.dart" would collide. | |
3858 qualifiedPath = uri.pathSegments.skip(1).join(separator); | |
3859 } else if (uri.path.startsWith(buildRoot)) { | |
Paul Berry
2016/04/28 15:49:30
This won't be correct on Windows, because uri.path
| |
3860 qualifiedPath = | |
3861 uri.path.substring(buildRoot.length).replaceAll('/', separator); | |
Paul Berry
2016/04/28 15:49:30
Use path.separator instead of '/'.
| |
3862 } else { | |
3863 // We don't have a unique name. | |
3864 throw 'Invalid build root. $buildRoot does not contain ${uri.path}'; | |
Siggi Cherem (dart-lang)
2016/04/28 15:13:28
nit: maybe rephrase as "Invalid build root. ${uri.
vsm
2016/04/28 15:31:45
I was thinking "contain" in the directory sense no
Siggi Cherem (dart-lang)
2016/04/28 15:43:49
Ah! :) makes sense. maybe: "is not a parent of"?
| |
3865 } | |
3866 return pathToJSIdentifier(qualifiedPath); | |
3842 } | 3867 } |
3843 | 3868 |
3844 /// Shorthand for identifier-like property names. | 3869 /// Shorthand for identifier-like property names. |
3845 /// For now, we emit them as strings and the printer restores them to | 3870 /// For now, we emit them as strings and the printer restores them to |
3846 /// identifiers if it can. | 3871 /// identifiers if it can. |
3847 // TODO(jmesserly): avoid the round tripping through quoted form. | 3872 // TODO(jmesserly): avoid the round tripping through quoted form. |
3848 JS.LiteralString _propertyName(String name) => js.string(name, "'"); | 3873 JS.LiteralString _propertyName(String name) => js.string(name, "'"); |
3849 | 3874 |
3850 // TODO(jacobr): we would like to do something like the following | 3875 // TODO(jacobr): we would like to do something like the following |
3851 // but we don't have summary support yet. | 3876 // but we don't have summary support yet. |
(...skipping 13 matching lines...) Expand all Loading... | |
3865 } | 3890 } |
3866 | 3891 |
3867 bool isLibraryPrefix(Expression node) => | 3892 bool isLibraryPrefix(Expression node) => |
3868 node is SimpleIdentifier && node.staticElement is PrefixElement; | 3893 node is SimpleIdentifier && node.staticElement is PrefixElement; |
3869 | 3894 |
3870 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 3895 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
3871 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 3896 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
3872 | 3897 |
3873 bool _isDartRuntime(LibraryElement l) => | 3898 bool _isDartRuntime(LibraryElement l) => |
3874 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 3899 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |