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:convert' show JSON, JsonEncoder; | 5 import 'dart:convert' show JSON, JsonEncoder; |
6 import 'dart:io' show Directory, File, Platform, Process; | 6 import 'dart:io' show Directory, File, Platform, Process; |
7 | 7 |
8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
9 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
10 import 'package:source_maps/source_maps.dart' as srcmaps show Printer; | 10 import 'package:source_maps/source_maps.dart' as srcmaps show Printer; |
11 import 'package:source_maps/source_maps.dart' show SourceMapSpan; | 11 import 'package:source_maps/source_maps.dart' show SourceMapSpan; |
12 import 'package:source_span/source_span.dart' show SourceLocation; | 12 import 'package:source_span/source_span.dart' show SourceLocation; |
13 | 13 |
14 import '../js/js_ast.dart' as JS; | 14 import '../js/js_ast.dart' as JS; |
15 import '../utils.dart' show FileSystem, computeHash, locationForOffset; | 15 import '../utils.dart' show FileSystem, computeHash, locationForOffset; |
16 | 16 |
17 import 'js_names.dart' show TemporaryNamer; | 17 import 'js_names.dart' show TemporaryNamer; |
18 | 18 |
19 String writeJsLibrary( | 19 void writeJsLibrary(JS.Program jsTree, String outputPath, String inputDir, |
20 JS.Program jsTree, String outputPath, String inputDir, Uri serverUri, | |
21 {bool emitSourceMaps: false, | 20 {bool emitSourceMaps: false, |
22 bool emitTypes: false, | 21 bool emitTypes: false, |
23 FileSystem fileSystem}) { | 22 FileSystem fileSystem}) { |
24 var outFilename = path.basename(outputPath); | 23 var outFilename = path.basename(outputPath); |
25 var outDir = path.dirname(outputPath); | 24 var outDir = path.dirname(outputPath); |
26 | 25 |
27 JS.JavaScriptPrintingContext context; | 26 JS.JavaScriptPrintingContext context; |
28 if (emitSourceMaps) { | 27 if (emitSourceMaps) { |
29 var printer = new srcmaps.Printer(outFilename); | 28 var printer = new srcmaps.Printer(outFilename); |
30 context = | 29 context = new SourceMapPrintingContext(printer, outDir, inputDir, null); |
31 new SourceMapPrintingContext(printer, outDir, inputDir, serverUri); | |
32 } else { | 30 } else { |
33 context = new JS.SimpleJavaScriptPrintingContext(); | 31 context = new JS.SimpleJavaScriptPrintingContext(); |
34 } | 32 } |
35 | 33 |
36 var opts = new JS.JavaScriptPrintingOptions( | 34 var opts = new JS.JavaScriptPrintingOptions( |
37 emitTypes: emitTypes, | 35 emitTypes: emitTypes, |
38 allowKeywordsInProperties: true, | 36 allowKeywordsInProperties: true, |
39 allowSingleLineIfStatements: true); | 37 allowSingleLineIfStatements: true); |
40 var jsNamer = new TemporaryNamer(jsTree); | 38 var jsNamer = new TemporaryNamer(jsTree); |
41 jsTree.accept(new JS.Printer(opts, context, localNamer: jsNamer)); | 39 jsTree.accept(new JS.Printer(opts, context, localNamer: jsNamer)); |
(...skipping 20 matching lines...) Expand all Loading... |
62 fileSystem.writeAsStringSync('$outputPath.map', '$sourceMapText\n'); | 60 fileSystem.writeAsStringSync('$outputPath.map', '$sourceMapText\n'); |
63 } else { | 61 } else { |
64 text = (context as JS.SimpleJavaScriptPrintingContext).getText(); | 62 text = (context as JS.SimpleJavaScriptPrintingContext).getText(); |
65 } | 63 } |
66 fileSystem.writeAsStringSync(outputPath, text); | 64 fileSystem.writeAsStringSync(outputPath, text); |
67 if (jsTree.scriptTag != null) { | 65 if (jsTree.scriptTag != null) { |
68 // Mark executable. | 66 // Mark executable. |
69 // TODO(jmesserly): should only do this if the input file was executable? | 67 // TODO(jmesserly): should only do this if the input file was executable? |
70 if (!Platform.isWindows) Process.runSync('chmod', ['+x', outputPath]); | 68 if (!Platform.isWindows) Process.runSync('chmod', ['+x', outputPath]); |
71 } | 69 } |
72 | |
73 return computeHash(text); | |
74 } | 70 } |
75 | 71 |
76 class SourceMapPrintingContext extends JS.JavaScriptPrintingContext { | 72 class SourceMapPrintingContext extends JS.JavaScriptPrintingContext { |
77 final srcmaps.Printer printer; | 73 final srcmaps.Printer printer; |
78 final String outputDir; | 74 final String outputDir; |
79 final String inputDir; | 75 final String inputDir; |
80 | 76 |
81 // TODO(vsm): we could abstract this out and have a generic Uri mapping | 77 final Uri baseUri; |
82 // instead of hardcoding a notion of a server uri. | |
83 final Uri serverUri; | |
84 | 78 |
85 CompilationUnit unit; | 79 CompilationUnit unit; |
86 Uri uri; | 80 Uri uri; |
87 | 81 |
88 SourceMapPrintingContext( | 82 SourceMapPrintingContext( |
89 this.printer, this.outputDir, this.inputDir, this.serverUri); | 83 this.printer, this.outputDir, this.inputDir, this.baseUri); |
90 | 84 |
91 void emit(String string) { | 85 void emit(String string) { |
92 printer.add(string); | 86 printer.add(string); |
93 } | 87 } |
94 | 88 |
95 AstNode _currentTopLevelDeclaration; | 89 AstNode _currentTopLevelDeclaration; |
96 | 90 |
97 void enterNode(JS.Node jsNode) { | 91 void enterNode(JS.Node jsNode) { |
98 AstNode node = jsNode.sourceInformation; | 92 AstNode node = jsNode.sourceInformation; |
99 if (node == null || node.offset == -1) return; | 93 if (node == null || node.offset == -1) return; |
(...skipping 17 matching lines...) Expand all Loading... |
117 printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true)); | 111 printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true)); |
118 } else { | 112 } else { |
119 printer.mark(loc); | 113 printer.mark(loc); |
120 } | 114 } |
121 } | 115 } |
122 | 116 |
123 SourceLocation _location(int offset) => | 117 SourceLocation _location(int offset) => |
124 locationForOffset(unit.lineInfo, uri, offset); | 118 locationForOffset(unit.lineInfo, uri, offset); |
125 | 119 |
126 Uri _makeRelativeUri(Uri src) { | 120 Uri _makeRelativeUri(Uri src) { |
127 if (serverUri == null) { | 121 if (baseUri == null) { |
128 return new Uri(path: path.relative(src.path, from: outputDir)); | 122 return new Uri(path: path.relative(src.path, from: outputDir)); |
129 } else { | 123 } else { |
130 if (src.path.startsWith('/')) { | 124 if (src.path.startsWith('/')) { |
131 return serverUri.resolve(path.relative(src.path, from: inputDir)); | 125 return baseUri.resolve(path.relative(src.path, from: inputDir)); |
132 } else { | 126 } else { |
133 return serverUri.resolve(path.join('packages', src.path)); | 127 return baseUri.resolve(path.join('packages', src.path)); |
134 } | 128 } |
135 } | 129 } |
136 } | 130 } |
137 | 131 |
138 void exitNode(JS.Node jsNode) { | 132 void exitNode(JS.Node jsNode) { |
139 AstNode node = jsNode.sourceInformation; | 133 AstNode node = jsNode.sourceInformation; |
140 if (unit == null || node == null || node.offset == -1) return; | 134 if (unit == null || node == null || node.offset == -1) return; |
141 | 135 |
142 // TODO(jmesserly): in many cases marking the end will be unnecessary. | 136 // TODO(jmesserly): in many cases marking the end will be unnecessary. |
143 printer.mark(_location(node.end)); | 137 printer.mark(_location(node.end)); |
144 | 138 |
145 if (_currentTopLevelDeclaration == node) { | 139 if (_currentTopLevelDeclaration == node) { |
146 unit = null; | 140 unit = null; |
147 uri = null; | 141 uri = null; |
148 _currentTopLevelDeclaration == null; | 142 _currentTopLevelDeclaration == null; |
149 return; | 143 return; |
150 } | 144 } |
151 } | 145 } |
152 | 146 |
153 String _getIdentifier(AstNode node) { | 147 String _getIdentifier(AstNode node) { |
154 if (node is SimpleIdentifier) return node.name; | 148 if (node is SimpleIdentifier) return node.name; |
155 return null; | 149 return null; |
156 } | 150 } |
157 } | 151 } |
OLD | NEW |