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 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
7 | 7 |
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 | 123 |
124 /// The current function body being compiled. | 124 /// The current function body being compiled. |
125 FunctionBody _currentFunction; | 125 FunctionBody _currentFunction; |
126 | 126 |
127 /// Helper class for emitting elements in the proper order to allow | 127 /// Helper class for emitting elements in the proper order to allow |
128 /// JS to load the module. | 128 /// JS to load the module. |
129 ElementLoader _loader; | 129 ElementLoader _loader; |
130 | 130 |
131 BuildUnit _buildUnit; | 131 BuildUnit _buildUnit; |
132 | 132 |
133 String _buildRoot; | 133 String _libraryRoot; |
134 | 134 |
135 bool _superAllowed = true; | 135 bool _superAllowed = true; |
136 | 136 |
137 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; | 137 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; |
138 List<JS.Method> _superHelpers = <JS.Method>[]; | 138 List<JS.Method> _superHelpers = <JS.Method>[]; |
139 | 139 |
140 List<TypeParameterType> _typeParamInConst = null; | 140 List<TypeParameterType> _typeParamInConst = null; |
141 | 141 |
142 /// Whether we are currently generating code for the body of a `JS()` call. | 142 /// Whether we are currently generating code for the body of a `JS()` call. |
143 bool _isInForeignJS = false; | 143 bool _isInForeignJS = false; |
(...skipping 17 matching lines...) Expand all Loading... |
161 | 161 |
162 LibraryElement get currentLibrary => _loader.currentElement.library; | 162 LibraryElement get currentLibrary => _loader.currentElement.library; |
163 | 163 |
164 /// The main entry point to JavaScript code generation. | 164 /// The main entry point to JavaScript code generation. |
165 /// | 165 /// |
166 /// Takes the metadata for the build unit, as well as resolved trees and | 166 /// Takes the metadata for the build unit, as well as resolved trees and |
167 /// errors, and computes the output module code and optionally the source map. | 167 /// errors, and computes the output module code and optionally the source map. |
168 JSModuleFile compile(BuildUnit unit, List<CompilationUnit> compilationUnits, | 168 JSModuleFile compile(BuildUnit unit, List<CompilationUnit> compilationUnits, |
169 List<String> errors) { | 169 List<String> errors) { |
170 _buildUnit = unit; | 170 _buildUnit = unit; |
171 _buildRoot = _buildUnit.buildRoot; | 171 _libraryRoot = _buildUnit.libraryRoot; |
172 if (!_buildRoot.endsWith(separator)) { | 172 if (!_libraryRoot.endsWith(separator)) { |
173 _buildRoot = '$_buildRoot${separator}'; | 173 _libraryRoot = '$_libraryRoot${separator}'; |
174 } | 174 } |
175 | 175 |
176 var jsTree = _emitModule(compilationUnits); | 176 var jsTree = _emitModule(compilationUnits); |
177 var codeAndSourceMap = _writeJSText(unit, jsTree); | 177 var codeAndSourceMap = _writeJSText(unit, jsTree); |
178 | 178 |
179 List<int> summary; | 179 List<int> summary; |
180 if (options.summarizeApi) { | 180 if (options.summarizeApi) { |
181 var assembler = new PackageBundleAssembler(); | 181 var assembler = new PackageBundleAssembler(); |
182 compilationUnits | 182 compilationUnits |
183 .map((u) => u.element.library) | 183 .map((u) => u.element.library) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 compilationUnits = CoercionReifier.reify(compilationUnits); | 224 compilationUnits = CoercionReifier.reify(compilationUnits); |
225 | 225 |
226 // Initialize our library variables. | 226 // Initialize our library variables. |
227 var items = <JS.ModuleItem>[]; | 227 var items = <JS.ModuleItem>[]; |
228 for (var unit in compilationUnits) { | 228 for (var unit in compilationUnits) { |
229 var library = unit.element.library; | 229 var library = unit.element.library; |
230 if (unit.element != library.definingCompilationUnit) continue; | 230 if (unit.element != library.definingCompilationUnit) continue; |
231 | 231 |
232 var libraryTemp = _isDartRuntime(library) | 232 var libraryTemp = _isDartRuntime(library) |
233 ? _runtimeLibVar | 233 ? _runtimeLibVar |
234 : new JS.TemporaryId(jsLibraryName(_buildRoot, library)); | 234 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); |
235 _libraries[library] = libraryTemp; | 235 _libraries[library] = libraryTemp; |
236 items.add(new JS.ExportDeclaration( | 236 items.add(new JS.ExportDeclaration( |
237 js.call('const # = Object.create(null)', [libraryTemp]))); | 237 js.call('const # = Object.create(null)', [libraryTemp]))); |
238 | 238 |
239 // dart:_runtime has a magic module that holds extenstion method symbols. | 239 // dart:_runtime has a magic module that holds extenstion method symbols. |
240 // TODO(jmesserly): find a cleaner design for this. | 240 // TODO(jmesserly): find a cleaner design for this. |
241 if (_isDartRuntime(library)) { | 241 if (_isDartRuntime(library)) { |
242 items.add(new JS.ExportDeclaration( | 242 items.add(new JS.ExportDeclaration( |
243 js.call('const # = Object.create(null)', [_dartxVar]))); | 243 js.call('const # = Object.create(null)', [_dartxVar]))); |
244 } | 244 } |
(...skipping 4937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5182 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 5182 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
5183 | 5183 |
5184 FunctionBody _functionBody(node) => | 5184 FunctionBody _functionBody(node) => |
5185 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 5185 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
5186 | 5186 |
5187 /// Returns the canonical name to refer to the Dart library. | 5187 /// Returns the canonical name to refer to the Dart library. |
5188 JS.Identifier emitLibraryName(LibraryElement library) { | 5188 JS.Identifier emitLibraryName(LibraryElement library) { |
5189 // It's either one of the libraries in this module, or it's an import. | 5189 // It's either one of the libraries in this module, or it's an import. |
5190 return _libraries[library] ?? | 5190 return _libraries[library] ?? |
5191 _imports.putIfAbsent(library, | 5191 _imports.putIfAbsent(library, |
5192 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library))); | 5192 () => new JS.TemporaryId(jsLibraryName(_libraryRoot, library))); |
5193 } | 5193 } |
5194 | 5194 |
5195 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/( | 5195 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/( |
5196 JS.Node/*=T*/ node, AstNode original, | 5196 JS.Node/*=T*/ node, AstNode original, |
5197 [Element element]) { | 5197 [Element element]) { |
5198 if (options.closure && element != null) { | 5198 if (options.closure && element != null) { |
5199 node = node.withClosureAnnotation(closureAnnotationFor( | 5199 node = node.withClosureAnnotation(closureAnnotationFor( |
5200 node, original, element, namedArgumentTemp.name)) as dynamic/*=T*/; | 5200 node, original, element, namedArgumentTemp.name)) as dynamic/*=T*/; |
5201 } | 5201 } |
5202 return node..sourceInformation = original; | 5202 return node..sourceInformation = original; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5308 // method level. | 5308 // method level. |
5309 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true; | 5309 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true; |
5310 | 5310 |
5311 return path.endsWith(".template.dart"); | 5311 return path.endsWith(".template.dart"); |
5312 } | 5312 } |
5313 } | 5313 } |
5314 | 5314 |
5315 /// Choose a canonical name from the library element. | 5315 /// Choose a canonical name from the library element. |
5316 /// This never uses the library's name (the identifier in the `library` | 5316 /// This never uses the library's name (the identifier in the `library` |
5317 /// declaration) as it doesn't have any meaningful rules enforced. | 5317 /// declaration) as it doesn't have any meaningful rules enforced. |
5318 String jsLibraryName(String buildRoot, LibraryElement library) { | 5318 String jsLibraryName(String libraryRoot, LibraryElement library) { |
5319 var uri = library.source.uri; | 5319 var uri = library.source.uri; |
5320 if (uri.scheme == 'dart') { | 5320 if (uri.scheme == 'dart') { |
5321 return uri.path; | 5321 return uri.path; |
5322 } | 5322 } |
5323 // TODO(vsm): This is not necessarily unique if '__' appears in a file name. | 5323 // TODO(vsm): This is not necessarily unique if '__' appears in a file name. |
5324 var separator = '__'; | 5324 var separator = '__'; |
5325 String qualifiedPath; | 5325 String qualifiedPath; |
5326 if (uri.scheme == 'package') { | 5326 if (uri.scheme == 'package') { |
5327 // Strip the package name. | 5327 // Strip the package name. |
5328 // TODO(vsm): This is not unique if an escaped '/'appears in a filename. | 5328 // TODO(vsm): This is not unique if an escaped '/'appears in a filename. |
5329 // E.g., "foo/bar.dart" and "foo$47bar.dart" would collide. | 5329 // E.g., "foo/bar.dart" and "foo$47bar.dart" would collide. |
5330 qualifiedPath = uri.pathSegments.skip(1).join(separator); | 5330 qualifiedPath = uri.pathSegments.skip(1).join(separator); |
5331 } else if (uri.toFilePath().startsWith(buildRoot)) { | 5331 } else if (uri.toFilePath().startsWith(libraryRoot)) { |
5332 qualifiedPath = | 5332 qualifiedPath = |
5333 uri.path.substring(buildRoot.length).replaceAll('/', separator); | 5333 uri.path.substring(libraryRoot.length).replaceAll('/', separator); |
5334 } else { | 5334 } else { |
5335 // We don't have a unique name. | 5335 // We don't have a unique name. |
5336 throw 'Invalid build root. $buildRoot does not contain ${uri.toFilePath()}'; | 5336 throw 'Invalid library root. $libraryRoot does not contain ${uri.toFilePath(
)}'; |
5337 } | 5337 } |
5338 return pathToJSIdentifier(qualifiedPath); | 5338 return pathToJSIdentifier(qualifiedPath); |
5339 } | 5339 } |
5340 | 5340 |
5341 /// Shorthand for identifier-like property names. | 5341 /// Shorthand for identifier-like property names. |
5342 /// For now, we emit them as strings and the printer restores them to | 5342 /// For now, we emit them as strings and the printer restores them to |
5343 /// identifiers if it can. | 5343 /// identifiers if it can. |
5344 // TODO(jmesserly): avoid the round tripping through quoted form. | 5344 // TODO(jmesserly): avoid the round tripping through quoted form. |
5345 JS.LiteralString _propertyName(String name) => js.string(name, "'"); | 5345 JS.LiteralString _propertyName(String name) => js.string(name, "'"); |
5346 | 5346 |
(...skipping 15 matching lines...) Expand all Loading... |
5362 } | 5362 } |
5363 | 5363 |
5364 bool isLibraryPrefix(Expression node) => | 5364 bool isLibraryPrefix(Expression node) => |
5365 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5365 node is SimpleIdentifier && node.staticElement is PrefixElement; |
5366 | 5366 |
5367 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5367 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
5368 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5368 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
5369 | 5369 |
5370 bool _isDartRuntime(LibraryElement l) => | 5370 bool _isDartRuntime(LibraryElement l) => |
5371 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5371 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |