| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of dart_backend; | 5 part of dart_backend; |
| 6 | 6 |
| 7 typedef bool IsSafeToRemoveTypeDeclarations( | 7 typedef bool IsSafeToRemoveTypeDeclarations( |
| 8 Map<ClassElement, Iterable<Element>> classMembers); | 8 Map<ClassElement, Iterable<Element>> classMembers); |
| 9 typedef void ElementCallback<E>(E element); | 9 typedef void ElementCallback<E>(E element); |
| 10 typedef void ElementPostProcessFunction( | 10 typedef void ElementPostProcessFunction( |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 static PlaceholderCollector collectPlaceholders( | 148 static PlaceholderCollector collectPlaceholders( |
| 149 DiagnosticListener listener, | 149 DiagnosticListener listener, |
| 150 MirrorRenamer mirrorRenamer, | 150 MirrorRenamer mirrorRenamer, |
| 151 FunctionElement mainFunction, | 151 FunctionElement mainFunction, |
| 152 LibraryInfo libraryInfo, | 152 LibraryInfo libraryInfo, |
| 153 ElementInfo elementInfo) { | 153 ElementInfo elementInfo) { |
| 154 // Create all necessary placeholders. | 154 // Create all necessary placeholders. |
| 155 PlaceholderCollector collector = new PlaceholderCollector( | 155 PlaceholderCollector collector = new PlaceholderCollector( |
| 156 listener, | 156 listener, |
| 157 mirrorRenamer, | 157 mirrorRenamer, |
| 158 libraryInfo.fixedMemberNames, | 158 libraryInfo.fixedDynamicNames, |
| 159 elementInfo.elementAsts, | 159 elementInfo.elementAsts, |
| 160 mainFunction); | 160 mainFunction); |
| 161 | 161 |
| 162 makePlaceholders(element) { | 162 makePlaceholders(element) { |
| 163 collector.collect(element); | 163 collector.collect(element); |
| 164 | 164 |
| 165 if (element.isClass) { | 165 if (element.isClass) { |
| 166 elementInfo.classMembers[element].forEach(makePlaceholders); | 166 elementInfo.classMembers[element].forEach(makePlaceholders); |
| 167 } | 167 } |
| 168 } | 168 } |
| 169 elementInfo.topLevelElements.forEach(makePlaceholders); | 169 elementInfo.topLevelElements.forEach(makePlaceholders); |
| 170 return collector; | 170 return collector; |
| 171 } | 171 } |
| 172 | 172 |
| 173 static PlaceholderRenamer createRenamer( | 173 static PlaceholderRenamer createRenamer( |
| 174 PlaceholderCollector collector, | 174 PlaceholderCollector collector, |
| 175 LibraryInfo libraryInfo, | 175 LibraryInfo libraryInfo, |
| 176 ElementInfo elementInfo, | 176 ElementInfo elementInfo, |
| 177 {bool enableMinification: false, | 177 {bool enableMinification: false, |
| 178 bool forceStripTypes: false, | 178 bool forceStripTypes: false, |
| 179 isSafeToRemoveTypeDeclarations}) { | 179 isSafeToRemoveTypeDeclarations}) { |
| 180 // Create renames. | 180 // Create renames. |
| 181 bool shouldCutDeclarationTypes = forceStripTypes | 181 bool shouldCutDeclarationTypes = forceStripTypes |
| 182 || (enableMinification | 182 || (enableMinification |
| 183 && isSafeToRemoveTypeDeclarations(elementInfo.classMembers)); | 183 && isSafeToRemoveTypeDeclarations(elementInfo.classMembers)); |
| 184 | 184 |
| 185 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer( | 185 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer( |
| 186 libraryInfo.fixedMemberNames, libraryInfo.reexportingLibraries, | 186 libraryInfo.fixedDynamicNames, |
| 187 libraryInfo.fixedStaticNames, |
| 188 libraryInfo.reexportingLibraries, |
| 187 cutDeclarationTypes: shouldCutDeclarationTypes, | 189 cutDeclarationTypes: shouldCutDeclarationTypes, |
| 188 enableMinification: enableMinification); | 190 enableMinification: enableMinification); |
| 189 | 191 |
| 190 placeholderRenamer.computeRenames(collector); | 192 placeholderRenamer.computeRenames(collector); |
| 191 return placeholderRenamer; | 193 return placeholderRenamer; |
| 192 } | 194 } |
| 193 | 195 |
| 194 static String astOutput(DiagnosticListener listener, | 196 static String astOutput(DiagnosticListener listener, |
| 195 ElementInfo elementInfo) { | 197 ElementInfo elementInfo) { |
| 196 // TODO(antonm): Ideally XML should be a separate backend. | 198 // TODO(antonm): Ideally XML should be a separate backend. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 208 elementInfo.classMembers[topLevel].forEach(outputElement); | 210 elementInfo.classMembers[topLevel].forEach(outputElement); |
| 209 } else { | 211 } else { |
| 210 outputElement(topLevel); | 212 outputElement(topLevel); |
| 211 } | 213 } |
| 212 } | 214 } |
| 213 return '<Program>\n$sb</Program>\n'; | 215 return '<Program>\n$sb</Program>\n'; |
| 214 } | 216 } |
| 215 } | 217 } |
| 216 | 218 |
| 217 class LibraryInfo { | 219 class LibraryInfo { |
| 218 final Set<String> fixedMemberNames; | 220 final Set<String> fixedStaticNames; |
| 221 final Set<String> fixedDynamicNames; |
| 219 final Map<Element, LibraryElement> reexportingLibraries; | 222 final Map<Element, LibraryElement> reexportingLibraries; |
| 220 final List<LibraryElement> userLibraries; | 223 final List<LibraryElement> userLibraries; |
| 221 | 224 |
| 222 LibraryInfo(this.fixedMemberNames, | 225 LibraryInfo(this.fixedStaticNames, |
| 226 this.fixedDynamicNames, |
| 223 this.reexportingLibraries, | 227 this.reexportingLibraries, |
| 224 this.userLibraries); | 228 this.userLibraries); |
| 225 | 229 |
| 226 static LibraryInfo processLibraries( | 230 static LibraryInfo processLibraries( |
| 227 Iterable<LibraryElement> libraries, | 231 Iterable<LibraryElement> libraries, |
| 228 Iterable<AstElement> resolvedElements) { | 232 Iterable<AstElement> resolvedElements) { |
| 229 Set<String> fixedMemberNames = new Set<String>(); | 233 Set<String> fixedStaticNames = new Set<String>(); |
| 234 Set<String> fixedDynamicNames = new Set<String>(); |
| 230 Map<Element, LibraryElement> reexportingLibraries = | 235 Map<Element, LibraryElement> reexportingLibraries = |
| 231 <Element, LibraryElement>{}; | 236 <Element, LibraryElement>{}; |
| 232 List<LibraryElement> userLibraries = <LibraryElement>[]; | 237 List<LibraryElement> userLibraries = <LibraryElement>[]; |
| 233 // Conservatively traverse all platform libraries and collect member names. | 238 // Conservatively traverse all platform libraries and collect member names. |
| 234 // TODO(antonm): ideally we should only collect names of used members, | 239 // TODO(antonm): ideally we should only collect names of used members, |
| 235 // however as of today there are problems with names of some core library | 240 // however as of today there are problems with names of some core library |
| 236 // interfaces, most probably for interfaces of literals. | 241 // interfaces, most probably for interfaces of literals. |
| 237 | 242 |
| 238 for (LibraryElement library in libraries) { | 243 for (LibraryElement library in libraries) { |
| 239 if (!library.isPlatformLibrary) { | 244 if (!library.isPlatformLibrary) { |
| 240 userLibraries.add(library); | 245 userLibraries.add(library); |
| 241 continue; | 246 continue; |
| 242 } | 247 } |
| 243 library.forEachLocalMember((Element element) { | 248 library.forEachLocalMember((Element element) { |
| 244 if (element.isClass) { | 249 if (element.isClass) { |
| 245 ClassElement classElement = element; | 250 ClassElement classElement = element; |
| 246 assert(invariant(classElement, classElement.isResolved, | 251 assert(invariant(classElement, classElement.isResolved, |
| 247 message: "Unresolved platform class.")); | 252 message: "Unresolved platform class.")); |
| 248 classElement.forEachLocalMember((member) { | 253 classElement.forEachLocalMember((member) { |
| 249 String name = member.name; | 254 if (member.isInstanceMember) { |
| 250 // Skip operator names. | 255 fixedDynamicNames.add(member.name); |
| 251 if (!name.startsWith(r'operator$')) { | 256 } else { |
| 252 // Fetch name of named constructors and factories if any, | 257 fixedStaticNames.add(member.name); |
| 253 // otherwise store regular name. | |
| 254 // TODO(antonm): better way to analyze the name. | |
| 255 fixedMemberNames.add(name.split(r'$').last); | |
| 256 } | 258 } |
| 257 }); | 259 }); |
| 258 } | 260 } |
| 259 // Even class names are added due to a delicate problem we have: | 261 // Even class names are added due to a delicate problem we have: |
| 260 // if one imports dart:core with a prefix, we cannot tell prefix.name | 262 // if one imports dart:core with a prefix, we cannot tell prefix.name |
| 261 // from dynamic invocation (alas!). So we'd better err on preserving | 263 // from dynamic invocation (alas!). So we'd better err on preserving |
| 262 // those names. | 264 // those names. |
| 263 fixedMemberNames.add(element.name); | 265 fixedStaticNames.add(element.name); |
| 264 }); | 266 }); |
| 265 | 267 |
| 266 for (Element export in library.exports) { | 268 for (Element export in library.exports) { |
| 267 if (!library.isInternalLibrary && | 269 if (!library.isInternalLibrary && |
| 268 export.library.isInternalLibrary) { | 270 export.library.isInternalLibrary) { |
| 269 // If an element of an internal library is reexported by a platform | 271 // If an element of an internal library is reexported by a platform |
| 270 // library, we have to import the reexporting library instead of the | 272 // library, we have to import the reexporting library instead of the |
| 271 // internal library, because the internal library is an | 273 // internal library, because the internal library is an |
| 272 // implementation detail of dart2js. | 274 // implementation detail of dart2js. |
| 273 reexportingLibraries[export] = library; | 275 reexportingLibraries[export] = library; |
| 274 } | 276 } |
| 275 } | 277 } |
| 276 } | 278 } |
| 277 // As of now names of named optionals are not renamed. Therefore add all | 279 // As of now names of named optionals are not renamed. Therefore add all |
| 278 // field names used as named optionals into [fixedMemberNames]. | 280 // field names used as named optionals into [fixedMemberNames]. |
| 279 for (final element in resolvedElements) { | 281 for (final element in resolvedElements) { |
| 280 if (!element.isConstructor) continue; | 282 if (!element.isConstructor) continue; |
| 281 Link<Element> optionalParameters = | 283 Link<Element> optionalParameters = |
| 282 element.functionSignature.optionalParameters; | 284 element.functionSignature.optionalParameters; |
| 283 for (final optional in optionalParameters) { | 285 for (final optional in optionalParameters) { |
| 284 if (!optional.isInitializingFormal) continue; | 286 if (!optional.isInitializingFormal) continue; |
| 285 fixedMemberNames.add(optional.name); | 287 fixedDynamicNames.add(optional.name); |
| 286 } | 288 } |
| 287 } | 289 } |
| 288 // The VM will automatically invoke the call method of objects | 290 // The VM will automatically invoke the call method of objects |
| 289 // that are invoked as functions. Make sure to not rename that. | 291 // that are invoked as functions. Make sure to not rename that. |
| 290 fixedMemberNames.add('call'); | 292 fixedDynamicNames.add('call'); |
| 291 // TODO(antonm): TypeError.srcType and TypeError.dstType are defined in | |
| 292 // runtime/lib/error.dart. Overall, all DartVM specific libs should be | |
| 293 // accounted for. | |
| 294 fixedMemberNames.add('srcType'); | |
| 295 fixedMemberNames.add('dstType'); | |
| 296 | 293 |
| 297 return new LibraryInfo( | 294 return new LibraryInfo( |
| 298 fixedMemberNames, reexportingLibraries, userLibraries); | 295 fixedStaticNames, fixedDynamicNames, |
| 296 reexportingLibraries, userLibraries); |
| 299 } | 297 } |
| 300 } | 298 } |
| 301 | 299 |
| 302 class ElementInfo { | 300 class ElementInfo { |
| 303 final Map<Element, ElementAst> elementAsts; | 301 final Map<Element, ElementAst> elementAsts; |
| 304 final Iterable<Element> topLevelElements; | 302 final Iterable<Element> topLevelElements; |
| 305 final Map<ClassElement, Iterable<Element>> classMembers; | 303 final Map<ClassElement, Iterable<Element>> classMembers; |
| 306 final Iterable<ClassElement> emitNoMembersFor; | 304 final Iterable<ClassElement> emitNoMembersFor; |
| 307 | 305 |
| 308 ElementInfo(this.elementAsts, | 306 ElementInfo(this.elementAsts, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 ? "${outputPaths[libraryElement]}.dart" | 514 ? "${outputPaths[libraryElement]}.dart" |
| 517 : libraryElement.canonicalUri.toString(); | 515 : libraryElement.canonicalUri.toString(); |
| 518 if (dependency is Import) { | 516 if (dependency is Import) { |
| 519 unparser.unparseImportTag(uri); | 517 unparser.unparseImportTag(uri); |
| 520 } else { | 518 } else { |
| 521 unparser.unparseExportTag(uri); | 519 unparser.unparseExportTag(uri); |
| 522 } | 520 } |
| 523 } | 521 } |
| 524 } | 522 } |
| 525 } else { | 523 } else { |
| 526 for(LibraryElement library in placeholderRenamer.platformImports) { | 524 placeholderRenamer.platformImports.forEach( |
| 527 if (library.isPlatformLibrary && !library.isInternalLibrary) { | 525 (LibraryElement library, String prefix) { |
| 528 mainUnparser.unparseImportTag(library.canonicalUri.toString()); | 526 assert(library.isPlatformLibrary && !library.isInternalLibrary); |
| 527 mainUnparser.unparseImportTag(library.canonicalUri.toString()); |
| 528 if (prefix != null) { |
| 529 // Adding a prefixed import because (some) top-level access need |
| 530 // it to avoid shadowing. |
| 531 // TODO(johnniwinther): Avoid prefix-less import if not needed. |
| 532 mainUnparser.unparseImportTag(library.canonicalUri.toString(), |
| 533 prefix: prefix); |
| 529 } | 534 } |
| 530 } | 535 }); |
| 531 } | 536 } |
| 532 | 537 |
| 533 for (int i = 0; i < elementInfo.topLevelElements.length; i++) { | 538 for (int i = 0; i < elementInfo.topLevelElements.length; i++) { |
| 534 Element element = elementInfo.topLevelElements.elementAt(i); | 539 Element element = elementInfo.topLevelElements.elementAt(i); |
| 535 Node node = topLevelNodes[i]; | 540 Node node = topLevelNodes[i]; |
| 536 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser; | 541 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser; |
| 537 if (node is ClassNode) { | 542 if (node is ClassNode) { |
| 538 // TODO(smok): Filter out default constructors here. | 543 // TODO(smok): Filter out default constructors here. |
| 539 unparser.unparseClassWithBody(node, memberNodes[node]); | 544 unparser.unparseClassWithBody(node, memberNodes[node]); |
| 540 } else { | 545 } else { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 559 outputProvider("", "dart") | 564 outputProvider("", "dart") |
| 560 ..add(code) | 565 ..add(code) |
| 561 ..close(); | 566 ..close(); |
| 562 | 567 |
| 563 totalSize = code.length; | 568 totalSize = code.length; |
| 564 } | 569 } |
| 565 | 570 |
| 566 return totalSize; | 571 return totalSize; |
| 567 } | 572 } |
| 568 } | 573 } |
| OLD | NEW |