Index: web/web_command.dart |
diff --git a/web/web_command.dart b/web/web_command.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..72e49052a7d2bbd268246df597e2980a5d1e62c8 |
--- /dev/null |
+++ b/web/web_command.dart |
@@ -0,0 +1,215 @@ |
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+import 'dart:html' show HttpRequest; |
+import 'dart:convert' show BASE64; |
+ |
+import 'package:args/command_runner.dart'; |
+import 'package:analyzer/src/generated/source.dart' |
+ show Source, DartUriResolver; |
+import 'package:analyzer/src/summary/idl.dart' show PackageBundle; |
+import 'package:dev_compiler/src/compiler/compiler.dart' |
+ show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler; |
+import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; |
+ |
+import 'package:analyzer/src/generated/engine.dart' |
+ show AnalysisContext, AnalysisEngine, TimestampedData; |
+import 'package:analyzer/src/generated/sdk.dart' |
+ show DartSdk, SdkLibrary, SdkLibraryImpl; |
+import 'package:analyzer/src/generated/source.dart' |
+ show DartUriResolver, Source, SourceFactory, UriKind; |
+import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; |
+import 'package:analyzer/src/context/cache.dart' |
+ show AnalysisCache, CachePartition; |
+import 'package:analyzer/file_system/memory_file_system.dart' |
+ show MemoryResourceProvider; |
+import 'package:analyzer/file_system/file_system.dart' |
+ show ResourceProvider, ResourceUriResolver; |
+import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; |
+ |
+typedef void MessageHandler(Object message); |
+ |
+/// The command for invoking the modular compiler. |
+class CompileCommand extends Command { |
Jennifer Messerly
2016/07/27 21:38:33
Maybe rename this WebCompileCommand?
priscillalee
2016/07/27 23:48:33
Done.
|
+ get name => 'compile'; |
+ get description => 'Compile a set of Dart files into a JavaScript module.'; |
+ final MessageHandler messageHandler; |
+ final Function onload; |
Jennifer Messerly
2016/07/27 21:38:33
suggestion, declare a strong type here. `Function`
priscillalee
2016/07/27 23:48:33
Typedefs are a really good idea! Thanks for that s
|
+ |
+ CompileCommand(this.onload, {MessageHandler messageHandler}) |
+ : this.messageHandler = messageHandler ?? print { |
+ CompilerOptions.addArguments(argParser); |
+ AnalyzerOptions.addArguments(argParser); |
+ } |
+ |
+ @override |
+ String run() { |
+ HttpRequest request = new HttpRequest(); |
Jennifer Messerly
2016/07/27 21:38:33
style: I would probably write this as:
var re
priscillalee
2016/07/27 23:48:33
Done.
|
+ |
+ request.onReadyStateChange.listen((_) { |
Jennifer Messerly
2016/07/27 21:38:33
one way to convert this to async/await:
Future<C
priscillalee
2016/07/27 23:48:33
Wow, I love how the async syntax reads, and it'd b
Jennifer Messerly
2016/07/28 05:23:10
Ah, maybe not worth worrying about then. Offhand I
priscillalee
2016/07/28 17:15:52
Acknowledged.
|
+ if (request.readyState == HttpRequest.DONE && |
+ (request.status == 200 || request.status == 0)) { |
+ var response = request.responseText; |
+ var sdkBytes = BASE64.decode(response); |
+ Function result = setUpCompile(sdkBytes); |
+ onload(result); |
+ } |
+ }); |
+ |
+ request.open('get', 'dart_sdk.sum'); |
+ request.send(); |
+ |
+ return ""; |
+ } |
+ |
+ Function setUpCompile(List<int> sdkBytes) { |
Jennifer Messerly
2016/07/27 21:38:33
would be good to use a typedef for this function t
priscillalee
2016/07/27 23:48:33
Done.
|
+ var resourceProvider = new MemoryResourceProvider(); |
+ var packageBundle = new PackageBundle.fromBuffer(sdkBytes); |
+ var webDartSdk = |
+ new SummaryBasedDartSdk(true, packageBundle, resourceProvider); |
+ |
+ var sdkResolver = new DartUriResolver(webDartSdk); |
+ var fileResolvers = [new ResourceUriResolver(resourceProvider)]; |
+ |
+ var compiler = new ModuleCompiler( |
+ new AnalyzerOptions(dartSdkPath: '/dart-sdk'), |
+ sdkResolver: sdkResolver, |
+ fileResolvers: fileResolvers, |
+ resourceProvider: resourceProvider); |
+ |
+ var compilerOptions = new CompilerOptions.fromArguments(argResults); |
+ |
+ var number = 0; |
+ |
+ return (String dart, Function callback) { |
+ //Create a new virtual File that contains the given Dart source. |
+ number++; |
+ resourceProvider.newFile("/expression$number.dart", dart); |
+ |
+ var unit = |
+ new BuildUnit("", "", ["file:///expression$number.dart"], null); |
+ |
+ JSModuleFile module = compiler.compile(unit, compilerOptions); |
+ module.errors.forEach(messageHandler); |
+ |
+ if (!module.isValid) throw new CompileErrorException(); |
+ callback(module.code); //module.summaryBytes; |
Jennifer Messerly
2016/07/27 21:38:33
could this be a return value instead of a callback
priscillalee
2016/07/27 23:48:33
Done.
|
+ }; |
+ } |
+} |
+ |
+/// Thrown when the input source code has errors. |
+class CompileErrorException implements Exception { |
+ toString() => '\nPlease fix all errors before compiling (warnings are okay).'; |
+} |
+ |
+class WebDartSdk implements DartSdk { |
Jennifer Messerly
2016/07/27 21:38:33
we didn't end up using this right? So we could del
priscillalee
2016/07/27 23:48:33
Done.
|
+ final Map<Uri, _WebSdkSource> _sources = {}; |
+ final bool reportMissing; |
+ final Map<String, SdkLibrary> _libs = {}; |
+ final String sdkVersion = '0'; |
+ List<String> get uris => _sources.keys.map((uri) => '$uri').toList(); |
+ |
+ AnalysisContext context; |
+ DartUriResolver _resolver; |
+ DartUriResolver get resolver => _resolver; |
+ PackageBundle packageBundle; |
+ |
+ WebDartSdk(Map<String, String> sources, ResourceProvider resourceProvider, |
+ this.packageBundle, |
+ {this.reportMissing}) { |
+ context = new _SdkAnalysisContext(this); |
+ sources.forEach((uriString, contents) { |
+ var uri = Uri.parse(uriString); |
+ _sources[uri] = new _WebSdkSource(uri, contents); |
+ _libs[uriString] = new SdkLibraryImpl(uri.path) |
+ ..setDart2JsLibrary() |
+ ..setVmLibrary(); |
+ }); |
+ _resolver = new DartUriResolver(this); |
+ |
+ context.sourceFactory = |
+ new SourceFactory([_resolver], null, resourceProvider); |
+ } |
+ |
+ @override |
+ PackageBundle getSummarySdkBundle(bool strongMode) { |
+ return packageBundle; |
+ } |
+ |
+ List<SdkLibrary> get sdkLibraries => _libs.values.toList(); |
+ SdkLibrary getSdkLibrary(String dartUri) => _libs[dartUri]; |
+ Source mapDartUri(String dartUri) => _getSource(Uri.parse(dartUri)); |
+ |
+ Source fromEncoding(UriKind kind, Uri uri) { |
+ if (kind != UriKind.DART_URI) { |
+ throw new UnsupportedError('expected dart: uri kind, got $kind.'); |
+ } |
+ return _getSource(uri); |
+ } |
+ |
+ Source _getSource(Uri uri) { |
+ var src = _sources[uri]; |
+ if (src == null) { |
+ if (reportMissing) print('warning: missing mock for $uri.'); |
+ _sources[uri] = src = new _WebSdkSource(uri, 'library dart.${uri.path};'); |
+ } |
+ return src; |
+ } |
+ |
+ @override |
+ Source fromFileUri(Uri uri) { |
+ throw new UnsupportedError('WebDartSdk.fromFileUri'); |
+ } |
+} |
+ |
+class _WebSdkSource implements Source { |
+ /// Absolute URI which this source can be imported from. |
+ final Uri uri; |
+ final String _contents; |
+ |
+ _WebSdkSource(this.uri, this._contents); |
+ |
+ bool exists() => true; |
+ |
+ int get hashCode => uri.hashCode; |
+ |
+ final int modificationStamp = 1; |
+ |
+ TimestampedData<String> get contents => |
+ new TimestampedData(modificationStamp, _contents); |
+ |
+ String get encoding => "${uriKind.encoding}$uri"; |
+ |
+ Source get source => this; |
+ |
+ String get fullName => shortName; |
+ |
+ String get shortName => uri.path; |
+ |
+ UriKind get uriKind => UriKind.DART_URI; |
+ |
+ bool get isInSystemLibrary => true; |
+ |
+ Source resolveRelative(Uri relativeUri) => |
+ throw new UnsupportedError('not expecting relative urls in dart: mocks'); |
+ |
+ Uri resolveRelativeUri(Uri relativeUri) => |
+ throw new UnsupportedError('not expecting relative urls in dart: mocks'); |
+} |
+ |
+/// An [AnalysisContextImpl] that only contains sources for a Dart SDK. |
+class _SdkAnalysisContext extends AnalysisContextImpl { |
+ final DartSdk sdk; |
+ |
+ _SdkAnalysisContext(this.sdk); |
+ |
+ @override |
+ AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { |
+ if (factory == null) { |
+ return super.createCacheFromSourceFactory(factory); |
+ } |
+ return new AnalysisCache( |
+ <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]); |
+ } |
+} |