| 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 |