Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 HashSet, Queue; | 5 import 'dart:collection' show HashSet, Queue; |
| 6 import 'dart:convert' show JSON; | 6 import 'dart:convert' show JSON; |
| 7 import 'dart:io' show File; | 7 import 'dart:io' show File; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' | 9 import 'package:analyzer/analyzer.dart' |
| 10 show AnalysisError, CompilationUnit, ErrorSeverity; | 10 show AnalysisError, CompilationUnit, ErrorSeverity; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 /// If that is not desired, the analysis context must be pre-configured using | 147 /// If that is not desired, the analysis context must be pre-configured using |
| 148 /// summaries before calling this method. | 148 /// summaries before calling this method. |
| 149 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { | 149 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { |
| 150 var trees = <CompilationUnit>[]; | 150 var trees = <CompilationUnit>[]; |
| 151 var errors = <AnalysisError>[]; | 151 var errors = <AnalysisError>[]; |
| 152 | 152 |
| 153 var librariesToCompile = new Queue<LibraryElement>(); | 153 var librariesToCompile = new Queue<LibraryElement>(); |
| 154 | 154 |
| 155 var compilingSdk = false; | 155 var compilingSdk = false; |
| 156 for (var sourcePath in unit.sources) { | 156 for (var sourcePath in unit.sources) { |
| 157 var sourceUri = Uri.parse(sourcePath); | 157 var sourceUri = _sourceToUri(sourcePath); |
| 158 if (sourceUri.scheme == '') { | 158 if (sourceUri.scheme == "dart") { |
| 159 sourceUri = path.toUri(path.absolute(sourcePath)); | |
| 160 } else if (sourceUri.scheme == 'dart') { | |
| 161 compilingSdk = true; | 159 compilingSdk = true; |
| 162 } | 160 } |
| 163 Source source = context.sourceFactory.forUri2(sourceUri); | 161 var source = context.sourceFactory.forUri2(sourceUri); |
| 164 | 162 |
| 165 var fileUsage = 'You need to pass at least one existing .dart file as an' | 163 var fileUsage = 'You need to pass at least one existing .dart file as an' |
| 166 ' argument.'; | 164 ' argument.'; |
| 167 if (source == null) { | 165 if (source == null) { |
| 168 throw new UsageException( | 166 throw new UsageException( |
| 169 'Could not create a source for "$sourcePath". The file name is in' | 167 'Could not create a source for "$sourcePath". The file name is in' |
| 170 ' the wrong format or was not found.', | 168 ' the wrong format or was not found.', |
| 171 fileUsage); | 169 fileUsage); |
| 172 } else if (!source.exists()) { | 170 } else if (!source.exists()) { |
| 173 throw new UsageException( | 171 throw new UsageException( |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 /// complete libraries including all of their parts, as well as all libraries | 416 /// complete libraries including all of their parts, as well as all libraries |
| 419 /// that are part of a library cycle. | 417 /// that are part of a library cycle. |
| 420 final List<String> sources; | 418 final List<String> sources; |
| 421 | 419 |
| 422 /// Given an imported library URI, this will determine to what Dart/JS module | 420 /// Given an imported library URI, this will determine to what Dart/JS module |
| 423 /// it belongs to. | 421 /// it belongs to. |
| 424 // TODO(jmesserly): we should replace this with another way of tracking | 422 // TODO(jmesserly): we should replace this with another way of tracking |
| 425 // build units. | 423 // build units. |
| 426 final Func1<Source, String> libraryToModule; | 424 final Func1<Source, String> libraryToModule; |
| 427 | 425 |
| 428 BuildUnit(this.name, this.libraryRoot, this.sources, this.libraryToModule); | 426 BuildUnit( |
| 427 String modulePath, this.libraryRoot, this.sources, this.libraryToModule) | |
| 428 : name = '${path.toUri(modulePath)}'; | |
| 429 } | 429 } |
| 430 | 430 |
| 431 /// The output of Dart->JS compilation. | 431 /// The output of Dart->JS compilation. |
| 432 /// | 432 /// |
| 433 /// This contains the file contents of the JS module, as well as a list of | 433 /// This contains the file contents of the JS module, as well as a list of |
| 434 /// Dart libraries that are contained in this module. | 434 /// Dart libraries that are contained in this module. |
| 435 class JSModuleFile { | 435 class JSModuleFile { |
| 436 /// The name of this module. | 436 /// The name of this module. |
| 437 final String name; | 437 final String name; |
| 438 | 438 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 var tree = | 493 var tree = |
| 494 transformModuleFormat(format, moduleTree, singleOutFile: singleOutFile); | 494 transformModuleFormat(format, moduleTree, singleOutFile: singleOutFile); |
| 495 tree.accept( | 495 tree.accept( |
| 496 new JS.Printer(opts, printer, localNamer: new JS.TemporaryNamer(tree))); | 496 new JS.Printer(opts, printer, localNamer: new JS.TemporaryNamer(tree))); |
| 497 | 497 |
| 498 Map builtMap; | 498 Map builtMap; |
| 499 if (options.sourceMap && sourceMap != null) { | 499 if (options.sourceMap && sourceMap != null) { |
| 500 builtMap = | 500 builtMap = |
| 501 placeSourceMap(sourceMap.build(jsUrl), mapUrl, options.bazelMapping); | 501 placeSourceMap(sourceMap.build(jsUrl), mapUrl, options.bazelMapping); |
| 502 if (options.sourceMapComment) { | 502 if (options.sourceMapComment) { |
| 503 var relativeMapUrl = path | 503 var jsDir = path.dirname(path.fromUri(jsUrl)); |
| 504 .toUri( | 504 var relative = path.relative(path.fromUri(mapUrl), from: jsDir); |
| 505 path.relative(path.fromUri(mapUrl), from: path.dirname(jsUrl))) | 505 var relativeMapUrl = path.toUri(relative).toString(); |
| 506 .toString(); | |
| 507 assert(path.dirname(jsUrl) == path.dirname(mapUrl)); | 506 assert(path.dirname(jsUrl) == path.dirname(mapUrl)); |
| 508 printer.emit('\n//# sourceMappingURL='); | 507 printer.emit('\n//# sourceMappingURL='); |
| 509 printer.emit(relativeMapUrl); | 508 printer.emit(relativeMapUrl); |
| 510 printer.emit('\n'); | 509 printer.emit('\n'); |
| 511 } | 510 } |
| 512 } | 511 } |
| 513 | 512 |
| 514 var text = printer.getText(); | 513 var text = printer.getText(); |
| 515 var rawSourceMap = options.inlineSourceMap | 514 var rawSourceMap = options.inlineSourceMap |
| 516 ? js.escapedString(JSON.encode(builtMap), "'").value | 515 ? js.escapedString(JSON.encode(builtMap), "'").value |
| 517 : 'null'; | 516 : 'null'; |
| 518 text = text.replaceFirst(sourceMapHoleID, rawSourceMap); | 517 text = text.replaceFirst(sourceMapHoleID, rawSourceMap); |
| 519 | 518 |
| 520 return new JSModuleCode(text, builtMap); | 519 return new JSModuleCode(text, builtMap); |
| 521 } | 520 } |
| 522 | 521 |
| 523 /// Similar to [getCode] but immediately writes the resulting files. | 522 /// Similar to [getCode] but immediately writes the resulting files. |
| 524 /// | 523 /// |
| 525 /// If [mapPath] is not supplied but [options.sourceMap] is set, mapPath | 524 /// If [mapPath] is not supplied but [options.sourceMap] is set, mapPath |
| 526 /// will default to [jsPath].map. | 525 /// will default to [jsPath].map. |
| 527 void writeCodeSync(ModuleFormat format, String jsPath, | 526 void writeCodeSync(ModuleFormat format, String jsPath, |
| 528 {bool singleOutFile: false}) { | 527 {bool singleOutFile: false}) { |
| 529 String mapPath = jsPath + '.map'; | 528 String mapPath = jsPath + '.map'; |
| 530 var code = getCode(format, jsPath, mapPath, singleOutFile: singleOutFile); | 529 var code = getCode( |
| 530 format, path.toUri(jsPath).toString(), path.toUri(mapPath).toString(), | |
| 531 singleOutFile: singleOutFile); | |
| 531 var c = code.code; | 532 var c = code.code; |
| 532 if (singleOutFile) { | 533 if (singleOutFile) { |
| 533 // In singleOutFile mode we wrap each module in an eval statement to | 534 // In singleOutFile mode we wrap each module in an eval statement to |
| 534 // leverage sourceURL to improve the debugging experience when source maps | 535 // leverage sourceURL to improve the debugging experience when source maps |
| 535 // are not enabled. | 536 // are not enabled. |
| 536 // | 537 // |
| 537 // Note: We replace all `/` with `.` so that we don't break relative urls | 538 // Note: We replace all `/` with `.` so that we don't break relative urls |
| 538 // to sources in the original sourcemap. The name of this file is bogus | 539 // to sources in the original sourcemap. The name of this file is bogus |
| 539 // anyways, so it has very little effect on things. | 540 // anyways, so it has very little effect on things. |
| 540 c += '\n//# sourceURL=${name.replaceAll("/", ".")}.js\n'; | 541 c += '\n//# sourceURL=${name.replaceAll("/", ".")}.js\n'; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 568 /// The JSON of the source map, if generated, otherwise `null`. | 569 /// The JSON of the source map, if generated, otherwise `null`. |
| 569 /// | 570 /// |
| 570 /// The source paths will initially be absolute paths. They can be adjusted | 571 /// The source paths will initially be absolute paths. They can be adjusted |
| 571 /// using [placeSourceMap]. | 572 /// using [placeSourceMap]. |
| 572 final Map sourceMap; | 573 final Map sourceMap; |
| 573 | 574 |
| 574 JSModuleCode(this.code, this.sourceMap); | 575 JSModuleCode(this.code, this.sourceMap); |
| 575 } | 576 } |
| 576 | 577 |
| 577 /// Adjusts the source paths in [sourceMap] to be relative to [sourceMapPath], | 578 /// Adjusts the source paths in [sourceMap] to be relative to [sourceMapPath], |
| 578 /// and returns the new map. | 579 /// and returns the new map. Relative paths are in terms of URIs ('/'), not |
| 580 /// local OS paths (e.g., windows '\'). | |
| 579 // TODO(jmesserly): find a new home for this. | 581 // TODO(jmesserly): find a new home for this. |
| 580 Map placeSourceMap( | 582 Map placeSourceMap( |
| 581 Map sourceMap, String sourceMapPath, Map<String, String> bazelMappings) { | 583 Map sourceMap, String sourceMapPath, Map<String, String> bazelMappings) { |
| 582 var dir = path.dirname(sourceMapPath); | |
| 583 var map = new Map.from(sourceMap); | 584 var map = new Map.from(sourceMap); |
| 585 // Convert to a local file path if it's not. | |
| 586 sourceMapPath = path.fromUri(_sourceToUri(sourceMapPath)); | |
| 587 var sourceMapDir = path.dirname(path.absolute(sourceMapPath)); | |
| 584 var list = new List.from(map['sources']); | 588 var list = new List.from(map['sources']); |
| 585 map['sources'] = list; | 589 map['sources'] = list; |
| 586 String transformUri(String uri) { | 590 |
| 587 if (uri.startsWith('dart:')) return uri; | 591 String makeRelative(String sourcePath) { |
| 588 var match = bazelMappings[path.absolute(uri)]; | 592 var uri = _sourceToUri(sourcePath); |
| 593 if (uri.scheme == 'dart' || uri.scheme == 'package') return sourcePath; | |
| 594 | |
| 595 // Convert to a local file path if it's not. | |
| 596 sourcePath = path.absolute(path.fromUri(uri)); | |
| 597 | |
| 598 // Allow bazel mappings to override. | |
| 599 var match = bazelMappings[sourcePath]; | |
| 589 if (match != null) return match; | 600 if (match != null) return match; |
| 590 | 601 |
| 591 // Fall back to a relative path. | 602 // Fall back to a relative path against the source map itself. |
| 592 return path.toUri(path.relative(path.fromUri(uri), from: dir)).toString(); | 603 sourcePath = path.relative(sourcePath, from: sourceMapDir); |
| 604 | |
| 605 // Convert from relative local path to relative URI. | |
| 606 return path.toUri(sourcePath).path; | |
| 593 } | 607 } |
| 594 | 608 |
| 595 for (int i = 0; i < list.length; i++) { | 609 for (int i = 0; i < list.length; i++) { |
| 596 list[i] = transformUri(list[i]); | 610 list[i] = makeRelative(list[i]); |
| 597 } | 611 } |
| 598 map['file'] = transformUri(map['file']); | 612 map['file'] = makeRelative(map['file']); |
| 599 return map; | 613 return map; |
| 600 } | 614 } |
| 615 | |
| 616 // Convert a source string to a Uri. The [source] may be a Dart URI, a file URI , | |
|
Jennifer Messerly
2017/04/20 18:22:39
long line
vsm
2017/04/20 18:29:05
Done.
| |
| 617 // or a local win/mac/linux path. | |
| 618 Uri _sourceToUri(String source) { | |
| 619 var uri = Uri.parse(source); | |
| 620 var scheme = uri.scheme; | |
| 621 switch (scheme) { | |
| 622 case "dart": | |
| 623 case "package": | |
| 624 case "file": | |
| 625 // A valid URI. | |
| 626 return uri; | |
| 627 default: | |
| 628 // Assume a file path. | |
| 629 return new Uri.file(path.absolute(source)); | |
| 630 } | |
| 631 } | |
| OLD | NEW |