Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Side by Side Diff: pkg/dev_compiler/web/web_command.dart

Issue 2423313002: Emulate compiling a source file in the context of an existing library. Add --debugger-compile flag … (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 @JS() 4 @JS()
5 library dev_compiler.web.web_command; 5 library dev_compiler.web.web_command;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:convert';
8 import 'dart:html' show HttpRequest; 9 import 'dart:html' show HttpRequest;
9 import 'dart:convert' show BASE64;
10 10
11 import 'package:analyzer/dart/element/element.dart'
12 show
13 LibraryElement,
14 ImportElement,
15 ShowElementCombinator,
16 HideElementCombinator;
11 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; 17 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
12 import 'package:analyzer/file_system/memory_file_system.dart' 18 import 'package:analyzer/file_system/memory_file_system.dart'
13 show MemoryResourceProvider; 19 show MemoryResourceProvider;
14 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; 20 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
15 import 'package:analyzer/src/generated/source.dart' show DartUriResolver; 21 import 'package:analyzer/src/generated/source.dart' show DartUriResolver;
16 import 'package:analyzer/src/summary/idl.dart' show PackageBundle; 22 import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
17 import 'package:analyzer/src/summary/package_bundle_reader.dart' 23 import 'package:analyzer/src/summary/package_bundle_reader.dart'
18 show 24 show
19 SummaryDataStore, 25 SummaryDataStore,
20 InSummaryUriResolver, 26 InSummaryUriResolver,
21 InputPackagesResultProvider, 27 InputPackagesResultProvider,
22 InSummarySource; 28 InSummarySource;
29 import 'package:analyzer/src/dart/resolver/scope.dart' show Scope;
23 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; 30 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
24 31
25 import 'package:args/command_runner.dart'; 32 import 'package:args/command_runner.dart';
26 33
27 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; 34 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
28 import 'package:dev_compiler/src/compiler/compiler.dart' 35 import 'package:dev_compiler/src/compiler/compiler.dart'
29 show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler; 36 show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler;
30 37
31 import 'package:dev_compiler/src/compiler/module_builder.dart'; 38 import 'package:dev_compiler/src/compiler/module_builder.dart';
32 import 'package:js/js.dart'; 39 import 'package:js/js.dart';
40 import 'package:path/path.dart' as path;
33 41
34 typedef void MessageHandler(Object message); 42 typedef void MessageHandler(Object message);
35 43
36 @JS() 44 @JS()
37 @anonymous 45 @anonymous
38 class CompileResult { 46 class CompileResult {
39 external factory CompileResult( 47 external factory CompileResult(
40 {String code, List<String> errors, bool isValid}); 48 {String code, List<String> errors, bool isValid});
41 } 49 }
42 50
43 typedef CompileResult CompileModule( 51 typedef CompileModule(String imports, String body, String libraryName,
44 String code, String libraryName, String fileName); 52 String existingLibrary, String fileName);
45 53
46 /// The command for invoking the modular compiler. 54 /// The command for invoking the modular compiler.
47 class WebCompileCommand extends Command { 55 class WebCompileCommand extends Command {
48 get name => 'compile'; 56 get name => 'compile';
49 57
50 get description => 'Compile a set of Dart files into a JavaScript module.'; 58 get description => 'Compile a set of Dart files into a JavaScript module.';
51 final MessageHandler messageHandler; 59 final MessageHandler messageHandler;
52 60
53 WebCompileCommand({MessageHandler messageHandler}) 61 WebCompileCommand({MessageHandler messageHandler})
54 : this.messageHandler = messageHandler ?? print { 62 : this.messageHandler = messageHandler ?? print {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 true, packageBundle, resourceProvider); 103 true, packageBundle, resourceProvider);
96 var sdkResolver = new DartUriResolver(webDartSdk); 104 var sdkResolver = new DartUriResolver(webDartSdk);
97 105
98 var summaryDataStore = new SummaryDataStore([]); 106 var summaryDataStore = new SummaryDataStore([]);
99 for (var i = 0; i < summaryBytes.length; i++) { 107 for (var i = 0; i < summaryBytes.length; i++) {
100 var bytes = summaryBytes[i]; 108 var bytes = summaryBytes[i];
101 var url = summaryUrls[i]; 109 var url = summaryUrls[i];
102 var summaryBundle = new PackageBundle.fromBuffer(bytes); 110 var summaryBundle = new PackageBundle.fromBuffer(bytes);
103 summaryDataStore.addBundle(url, summaryBundle); 111 summaryDataStore.addBundle(url, summaryBundle);
104 } 112 }
105 var summaryResolver = new InSummaryUriResolver(resourceProvider, summaryData Store); 113 var summaryResolver =
114 new InSummaryUriResolver(resourceProvider, summaryDataStore);
106 115
107 var fileResolvers = [summaryResolver, resourceUriResolver]; 116 var fileResolvers = [summaryResolver, resourceUriResolver];
108 117
109 var compiler = new ModuleCompiler( 118 var compiler = new ModuleCompiler(
110 new AnalyzerOptions(dartSdkPath: '/dart-sdk'), 119 new AnalyzerOptions(dartSdkPath: '/dart-sdk'),
111 sdkResolver: sdkResolver, 120 sdkResolver: sdkResolver,
112 fileResolvers: fileResolvers, 121 fileResolvers: fileResolvers,
113 resourceProvider: resourceProvider); 122 resourceProvider: resourceProvider);
114 123
115 (compiler.context as AnalysisContextImpl).resultProvider = 124 var context = compiler.context as AnalysisContextImpl;
125 context.resultProvider =
116 new InputPackagesResultProvider(compiler.context, summaryDataStore); 126 new InputPackagesResultProvider(compiler.context, summaryDataStore);
117 127
118 var compilerOptions = new CompilerOptions.fromArguments(argResults); 128 var compilerOptions = new CompilerOptions.fromArguments(argResults);
119 129
120 CompileModule compileFn = 130 CompileModule compileFn = (String imports, String body, String libraryName,
121 (String sourceCode, String libraryName, String fileName) { 131 String existingLibrary, String fileName) {
122 // Create a new virtual File that contains the given Dart source. 132 // Create a new virtual File that contains the given Dart source.
123 resourceProvider.newFile("/$fileName", sourceCode); 133 String sourceCode;
134 if (existingLibrary == null) {
135 sourceCode = imports + body;
136 } else {
137 var dir = path.dirname(existingLibrary);
138 // Need to pull in all the imports from the existing library and
139 // re-export all privates as privates in this library.
140 var source = context.sourceFactory.forUri(existingLibrary);
141 if (source == null) {
142 throw "Unable to load source for library $existingLibrary";
143 }
124 144
125 var unit = new BuildUnit( 145 LibraryElement libraryElement = context.computeLibraryElement(source);
126 libraryName, "", ["file:///$fileName"], _moduleForLibrary); 146 if (libraryElement == null) {
147 throw "Unable to get library element.";
Jennifer Messerly 2016/10/18 18:46:01 do you know in what context this actually happens?
148 }
149 var sb = new StringBuffer(imports);
150 sb.write('\n');
151
152 // We set the private name prefix for scope resolution to an invalid
153 // character code so that the analyzer ignores normal Dart private
154 // scoping rules for top level names allowing REPL users to access
155 // privates in arbitrary libraries. The downside of this scheme is it is
156 // possible to get errors if privates in the current library and
157 // imported libraries happen to have exactly the same name.
158 Scope.PRIVATE_NAME_PREFIX = -1;
Jennifer Messerly 2016/10/18 18:46:01 Interesting. It seems better to add a feature expl
Brian Wilkerson 2016/10/18 19:16:44 I agree, this seems brittle. (I can't even guarant
159
160 // We emulate running code in the context of an existing library by
161 // importing that library and all libraries it imports.
162 sb.write('import ${JSON.encode(existingLibrary)};\n');
163
164 for (ImportElement importElement in libraryElement.imports) {
165 if (importElement.uri == null) continue;
166 var uri = importElement.uri;
167 // dart: and package: uris are not relative but the path package
168 // thinks they are. We have to provide absolute uris as our library
169 // has a different directory than the library we are pretending to be.
Brian Wilkerson 2016/10/18 19:16:44 It might be better to get the URI of the imported
170 if (path.isRelative(uri) &&
171 !uri.startsWith('package:') &&
172 !uri.startsWith('dart:')) {
173 uri = path.normalize(path.join(dir, uri));
174 }
175 sb.write('import ${JSON.encode(uri)}');
176 if (importElement.prefix != null)
177 sb.write(' as ${importElement.prefix.name}');
178 for (var combinator in importElement.combinators) {
179 if (combinator is ShowElementCombinator) {
180 sb.write(' show ${combinator.shownNames.join(', ')}');
181 } else if (combinator is HideElementCombinator) {
182 sb.write(' hide ${combinator.hiddenNames.join(', ')}');
183 } else {
184 throw 'Unexpected element combinator';
185 }
186 }
187 sb.write(';\n');
188 }
189 sb.write(body);
190 sourceCode = sb.toString();
191 }
192 resourceProvider.newFile(fileName, sourceCode);
193
194 var unit = new BuildUnit(libraryName, "", [fileName], _moduleForLibrary);
127 195
128 JSModuleFile module = compiler.compile(unit, compilerOptions); 196 JSModuleFile module = compiler.compile(unit, compilerOptions);
129 197
130 var moduleCode = module.isValid 198 var moduleCode = module.isValid
131 ? module 199 ? module
132 .getCode(ModuleFormat.legacy, false, unit.name, unit.name + '.map' ) 200 .getCode(ModuleFormat.legacy, true, unit.name, unit.name + '.map')
133 .code 201 .code
134 : ''; 202 : '';
135 203
136 return new CompileResult( 204 return new CompileResult(
137 code: moduleCode, isValid: module.isValid, errors: module.errors); 205 code: moduleCode, isValid: module.isValid, errors: module.errors);
138 }; 206 };
139 207
140 return allowInterop(compileFn); 208 return allowInterop(compileFn);
141 } 209 }
142 } 210 }
143 211
144 // Given path, determine corresponding dart library. 212 // Given path, determine corresponding dart library.
145 String _moduleForLibrary(source) { 213 String _moduleForLibrary(source) {
146 if (source is InSummarySource) { 214 if (source is InSummarySource) {
147 return source.summaryPath.substring(1).replaceAll('.api.ds', ''); 215 return source.summaryPath.substring(1).replaceAll('.api.ds', '');
148 } 216 }
149 return source.toString().substring(1).replaceAll('.dart', ''); 217 return source.toString().substring(1).replaceAll('.dart', '');
150 } 218 }
151 219
152 /// Thrown when the input source code has errors. 220 /// Thrown when the input source code has errors.
153 class CompileErrorException implements Exception { 221 class CompileErrorException implements Exception {
154 toString() => '\nPlease fix all errors before compiling (warnings are okay).'; 222 toString() => '\nPlease fix all errors before compiling (warnings are okay).';
155 } 223 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698