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 library dev_compiler.src.codegen.js_printer; | 5 library dev_compiler.src.codegen.js_printer; |
| 6 | 6 |
| 7 import 'dart:convert' show JSON, JsonEncoder; | 7 import 'dart:convert' show JSON, JsonEncoder; |
| 8 import 'dart:io' show Directory, File, Platform, Process; | 8 import 'dart:io' show Directory, File, Platform, Process; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; |
| 11 import 'package:path/path.dart' as path; | 11 import 'package:path/path.dart' as path; |
| 12 import 'package:source_maps/source_maps.dart' as srcmaps show Printer; | 12 import 'package:source_maps/source_maps.dart' as srcmaps show Printer; |
| 13 import 'package:source_maps/source_maps.dart' show SourceMapSpan; | 13 import 'package:source_maps/source_maps.dart' show SourceMapSpan; |
| 14 import 'package:source_span/source_span.dart' show SourceLocation; | 14 import 'package:source_span/source_span.dart' show SourceLocation; |
| 15 | 15 |
| 16 import '../js/js_ast.dart' as JS; | 16 import '../js/js_ast.dart' as JS; |
| 17 import '../utils.dart' show computeHash, locationForOffset; | 17 import '../utils.dart' show computeHash, locationForOffset; |
| 18 | 18 |
| 19 import 'js_names.dart' show TemporaryNamer; | 19 import 'js_names.dart' show TemporaryNamer; |
| 20 | 20 |
| 21 String writeJsLibrary(JS.Program jsTree, String outputPath, | 21 String writeJsLibrary(JS.Program jsTree, String outputPath, String inputDir, |
| 22 String serverUrl, | |
| 22 {bool emitSourceMaps: false, bool arrowFnBindThisWorkaround: false}) { | 23 {bool emitSourceMaps: false, bool arrowFnBindThisWorkaround: false}) { |
| 23 var outFilename = path.basename(outputPath); | 24 var outFilename = path.basename(outputPath); |
| 24 var outDir = path.dirname(outputPath); | 25 var outDir = path.dirname(outputPath); |
| 25 new Directory(outDir).createSync(recursive: true); | 26 new Directory(outDir).createSync(recursive: true); |
| 26 | 27 |
| 27 JS.JavaScriptPrintingContext context; | 28 JS.JavaScriptPrintingContext context; |
| 28 if (emitSourceMaps) { | 29 if (emitSourceMaps) { |
| 29 var printer = new srcmaps.Printer(outFilename); | 30 var printer = new srcmaps.Printer(outFilename); |
| 30 context = new SourceMapPrintingContext(printer, outDir); | 31 context = new SourceMapPrintingContext(printer, outDir, inputDir, serverUrl) ; |
| 31 } else { | 32 } else { |
| 32 context = new JS.SimpleJavaScriptPrintingContext(); | 33 context = new JS.SimpleJavaScriptPrintingContext(); |
| 33 } | 34 } |
| 34 | 35 |
| 35 var opts = new JS.JavaScriptPrintingOptions( | 36 var opts = new JS.JavaScriptPrintingOptions( |
| 36 allowKeywordsInProperties: true, | 37 allowKeywordsInProperties: true, |
| 37 arrowFnBindThisWorkaround: arrowFnBindThisWorkaround); | 38 arrowFnBindThisWorkaround: arrowFnBindThisWorkaround); |
| 38 var jsNamer = new TemporaryNamer(jsTree); | 39 var jsNamer = new TemporaryNamer(jsTree); |
| 39 jsTree.accept(new JS.Printer(opts, context, localNamer: jsNamer)); | 40 jsTree.accept(new JS.Printer(opts, context, localNamer: jsNamer)); |
| 40 | 41 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 65 // TODO(jmesserly): should only do this if the input file was executable? | 66 // TODO(jmesserly): should only do this if the input file was executable? |
| 66 if (!Platform.isWindows) Process.runSync('chmod', ['+x', outputPath]); | 67 if (!Platform.isWindows) Process.runSync('chmod', ['+x', outputPath]); |
| 67 } | 68 } |
| 68 | 69 |
| 69 return computeHash(text); | 70 return computeHash(text); |
| 70 } | 71 } |
| 71 | 72 |
| 72 class SourceMapPrintingContext extends JS.JavaScriptPrintingContext { | 73 class SourceMapPrintingContext extends JS.JavaScriptPrintingContext { |
| 73 final srcmaps.Printer printer; | 74 final srcmaps.Printer printer; |
| 74 final String outputDir; | 75 final String outputDir; |
| 76 final String inputDir; | |
| 77 final String serverUrl; | |
| 75 | 78 |
| 76 CompilationUnit unit; | 79 CompilationUnit unit; |
| 77 Uri uri; | 80 Uri uri; |
| 78 | 81 |
| 79 SourceMapPrintingContext(this.printer, this.outputDir); | 82 SourceMapPrintingContext(this.printer, this.outputDir, this.inputDir, this.ser verUrl); |
|
Jennifer Messerly
2015/12/16 18:40:07
slight factoring thing, I wonder if we should pass
vsm
2016/01/07 21:22:03
added a todo
| |
| 80 | 83 |
| 81 void emit(String string) { | 84 void emit(String string) { |
| 82 printer.add(string); | 85 printer.add(string); |
| 83 } | 86 } |
| 84 | 87 |
| 85 AstNode _currentTopLevelDeclaration; | 88 AstNode _currentTopLevelDeclaration; |
| 86 | 89 |
| 87 void enterNode(JS.Node jsNode) { | 90 void enterNode(JS.Node jsNode) { |
| 88 AstNode node = jsNode.sourceInformation; | 91 AstNode node = jsNode.sourceInformation; |
| 89 if (node == null || node.offset == -1) return; | 92 if (node == null || node.offset == -1) return; |
| 90 if (unit == null) { | 93 if (unit == null) { |
| 91 // This is a top-level declaration. Note: consecutive top-level | 94 // This is a top-level declaration. Note: consecutive top-level |
| 92 // declarations may come from different compilation units due to | 95 // declarations may come from different compilation units due to |
| 93 // parts. | 96 // parts. |
| 94 _currentTopLevelDeclaration = node; | 97 _currentTopLevelDeclaration = node; |
| 95 unit = node.getAncestor((n) => n is CompilationUnit); | 98 unit = node.getAncestor((n) => n is CompilationUnit); |
| 96 uri = _makeRelativeUri(unit.element.source.uri); | 99 uri = _makeRelativeUri(unit.element.source.uri); |
| 97 } | 100 } |
| 101 if (unit == null) return; | |
| 98 | 102 |
| 99 assert(unit != null); | 103 assert(unit != null); |
| 100 var loc = _location(node.offset); | 104 var loc = _location(node.offset); |
| 101 var name = _getIdentifier(node); | 105 var name = _getIdentifier(node); |
| 102 if (name != null) { | 106 if (name != null) { |
| 103 // TODO(jmesserly): mark only uses the beginning of the span, but | 107 // TODO(jmesserly): mark only uses the beginning of the span, but |
| 104 // we're required to pass this as a valid span. | 108 // we're required to pass this as a valid span. |
| 105 var end = _location(node.end); | 109 var end = _location(node.end); |
| 106 printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true)); | 110 printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true)); |
| 107 } else { | 111 } else { |
| 108 printer.mark(loc); | 112 printer.mark(loc); |
| 109 } | 113 } |
| 110 } | 114 } |
| 111 | 115 |
| 112 SourceLocation _location(int offset) => | 116 SourceLocation _location(int offset) => |
| 113 locationForOffset(unit.lineInfo, uri, offset); | 117 locationForOffset(unit.lineInfo, uri, offset); |
| 114 | 118 |
| 115 Uri _makeRelativeUri(Uri src) { | 119 Uri _makeRelativeUri(Uri src) { |
| 116 return new Uri(path: path.relative(src.path, from: outputDir)); | 120 if (serverUrl == null) { |
| 121 return new Uri(path: path.relative(src.path, from: outputDir)); | |
| 122 } else { | |
| 123 if (src.path.startsWith('/')) { | |
| 124 return new Uri(path: serverUrl + path.relative(src.path, from: inputDir) ); | |
|
Jennifer Messerly
2015/12/16 18:40:07
the name here's a little confusing, if this was a
vsm
2016/01/07 21:22:03
i think i was abusing the path argument to the Uri
| |
| 125 } else { | |
| 126 return new Uri(path: serverUrl + 'packages/' + src.path); | |
| 127 } | |
| 128 } | |
| 117 } | 129 } |
| 118 | 130 |
| 119 void exitNode(JS.Node jsNode) { | 131 void exitNode(JS.Node jsNode) { |
| 120 AstNode node = jsNode.sourceInformation; | 132 AstNode node = jsNode.sourceInformation; |
| 121 if (unit == null || node == null || node.offset == -1) return; | 133 if (unit == null || node == null || node.offset == -1) return; |
| 122 | 134 |
| 123 // TODO(jmesserly): in many cases marking the end will be unnecessary. | 135 // TODO(jmesserly): in many cases marking the end will be unnecessary. |
| 124 printer.mark(_location(node.end)); | 136 printer.mark(_location(node.end)); |
| 125 | 137 |
| 126 if (_currentTopLevelDeclaration == node) { | 138 if (_currentTopLevelDeclaration == node) { |
| 127 unit = null; | 139 unit = null; |
| 128 uri = null; | 140 uri = null; |
| 129 _currentTopLevelDeclaration == null; | 141 _currentTopLevelDeclaration == null; |
| 130 return; | 142 return; |
| 131 } | 143 } |
| 132 } | 144 } |
| 133 | 145 |
| 134 String _getIdentifier(AstNode node) { | 146 String _getIdentifier(AstNode node) { |
| 135 if (node is SimpleIdentifier) return node.name; | 147 if (node is SimpleIdentifier) return node.name; |
| 136 return null; | 148 return null; |
| 137 } | 149 } |
| 138 } | 150 } |
| OLD | NEW |