Chromium Code Reviews| 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 |