| Index: pkg/dart2js_incremental/lib/server.dart
|
| diff --git a/pkg/dart2js_incremental/lib/server.dart b/pkg/dart2js_incremental/lib/server.dart
|
| deleted file mode 100644
|
| index d2dc9a2235657671e643385bd5cf9a66c58c09f9..0000000000000000000000000000000000000000
|
| --- a/pkg/dart2js_incremental/lib/server.dart
|
| +++ /dev/null
|
| @@ -1,301 +0,0 @@
|
| -// Copyright (c) 2012, 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.
|
| -
|
| -library dart2js_incremental.server;
|
| -
|
| -import 'dart:io';
|
| -
|
| -import 'dart:async' show
|
| - Completer,
|
| - Future,
|
| - Stream,
|
| - StreamController,
|
| - StreamSubscription;
|
| -
|
| -import 'dart:convert' show
|
| - HtmlEscape,
|
| - JSON,
|
| - UTF8;
|
| -
|
| -import 'src/options.dart';
|
| -
|
| -import 'compiler.dart' show
|
| - CompilerEvent,
|
| - IncrementalKind,
|
| - compile;
|
| -
|
| -class Conversation {
|
| - HttpRequest request;
|
| - HttpResponse response;
|
| -
|
| - static const String PACKAGES_PATH = '/packages';
|
| -
|
| - static const String CONTENT_TYPE = HttpHeaders.CONTENT_TYPE;
|
| -
|
| - static Uri documentRoot = Uri.base;
|
| -
|
| - static Uri packageRoot = Uri.base.resolve('packages/');
|
| -
|
| - static Map<Uri, Future<String>> generatedFiles =
|
| - new Map<Uri, Future<String>>();
|
| -
|
| - static Map<Uri, StreamController<String>> updateControllers =
|
| - new Map<Uri, StreamController<String>>();
|
| -
|
| - Conversation(this.request, this.response);
|
| -
|
| - onClosed(_) {
|
| - if (response.statusCode == HttpStatus.OK) return;
|
| - print('Request for ${request.uri} ${response.statusCode}');
|
| - }
|
| -
|
| - Future notFound(Uri uri) {
|
| - response
|
| - ..headers.set(CONTENT_TYPE, 'text/html')
|
| - ..statusCode = HttpStatus.NOT_FOUND
|
| - ..write(htmlInfo("Not Found", "The file '$uri' could not be found."));
|
| - return response.close();
|
| - }
|
| -
|
| - Future badRequest(String problem) {
|
| - response
|
| - ..headers.set(CONTENT_TYPE, 'text/html')
|
| - ..statusCode = HttpStatus.BAD_REQUEST
|
| - ..write(
|
| - htmlInfo("Bad request", "Bad request '${request.uri}': $problem"));
|
| - return response.close();
|
| - }
|
| -
|
| - Future handleSocket() async {
|
| - StreamController<String> controller = updateControllers[request.uri];
|
| - if (controller != null) {
|
| - WebSocket socket = await WebSocketTransformer.upgrade(request);
|
| - print(
|
| - "Patches to ${request.uri} will be pushed to "
|
| - "${request.connectionInfo.remoteAddress.host}:"
|
| - "${request.connectionInfo.remotePort}.");
|
| - controller.stream.pipe(socket);
|
| - } else {
|
| - response.done
|
| - .then(onClosed)
|
| - .catchError(onError);
|
| - return await notFound(request.uri);
|
| - }
|
| - }
|
| -
|
| - Future handle() {
|
| - response.done
|
| - .then(onClosed)
|
| - .catchError(onError);
|
| -
|
| - Uri uri = request.uri;
|
| - if (uri.path.endsWith('/')) {
|
| - uri = uri.resolve('index.html');
|
| - }
|
| - if (uri.path.contains('..') || uri.path.contains('%')) {
|
| - return notFound(uri);
|
| - }
|
| - String path = uri.path;
|
| - Uri root = documentRoot;
|
| - if (path.startsWith('${PACKAGES_PATH}/')) {
|
| - root = packageRoot;
|
| - path = path.substring(PACKAGES_PATH.length);
|
| - }
|
| -
|
| - Uri resolvedRequest = root.resolve('.$path');
|
| - switch (request.method) {
|
| - case 'GET':
|
| - return handleGet(resolvedRequest);
|
| - default:
|
| - String method = const HtmlEscape().convert(request.method);
|
| - return badRequest("Unsupported method: '$method'");
|
| - }
|
| - }
|
| -
|
| - Future handleGet(Uri uri) async {
|
| - String path = uri.path;
|
| - var f = new File.fromUri(uri);
|
| - if (!await f.exists()) {
|
| - return await handleNonExistingFile(uri);
|
| - } else {
|
| - setContentType(path);
|
| - }
|
| - return await f.openRead().pipe(response);
|
| - }
|
| -
|
| - void setContentType(String path) {
|
| - if (path.endsWith('.html')) {
|
| - response.headers.set(CONTENT_TYPE, 'text/html');
|
| - } else if (path.endsWith('.dart')) {
|
| - response.headers.set(CONTENT_TYPE, 'application/dart');
|
| - } else if (path.endsWith('.js')) {
|
| - response.headers.set(CONTENT_TYPE, 'application/javascript');
|
| - } else if (path.endsWith('.ico')) {
|
| - response.headers.set(CONTENT_TYPE, 'image/x-icon');
|
| - } else if (path.endsWith('.appcache')) {
|
| - response.headers.set(CONTENT_TYPE, 'text/cache-manifest');
|
| - } else if (path.endsWith('.css')) {
|
| - response.headers.set(CONTENT_TYPE, 'text/css');
|
| - } else if (path.endsWith('.png')) {
|
| - response.headers.set(CONTENT_TYPE, 'image/png');
|
| - }
|
| - }
|
| -
|
| - Future handleNonExistingFile(Uri uri) async {
|
| - String path = uri.path;
|
| - String generated = await generatedFiles[request.uri];
|
| - if (generated != null) {
|
| - print("Serving ${request.uri} from memory.");
|
| - setContentType(path);
|
| - response.write(generated);
|
| - return await response.close();
|
| - }
|
| - if (path.endsWith('.dart.js')) {
|
| - Uri dartScript = uri.resolve(path.substring(0, path.length - 3));
|
| - if (await new File.fromUri(dartScript).exists()) {
|
| - return await compileToJavaScript(dartScript);
|
| - }
|
| - }
|
| - return await notFound(request.uri);
|
| - }
|
| -
|
| - compileToJavaScript(Uri dartScript) {
|
| - Uri outputUri = request.uri;
|
| - Completer<String> completer = new Completer<String>();
|
| - generatedFiles[outputUri] = completer.future;
|
| - StreamController controller = updateControllers[outputUri];
|
| - if (controller != null) {
|
| - controller.close();
|
| - }
|
| - updateControllers[outputUri] = new StreamController<String>.broadcast();
|
| - print("Compiling $dartScript to $outputUri.");
|
| - StreamSubscription<CompilerEvent> subscription;
|
| - subscription = compile(dartScript).listen((CompilerEvent event) {
|
| - subscription.onData(
|
| - (CompilerEvent event) => onCompilerEvent(completer, event));
|
| - if (event.kind != IncrementalKind.FULL) {
|
| - notFound(request.uri);
|
| - // TODO(ahe): Do something about this situation.
|
| - } else {
|
| - print("Done compiling $dartScript to $outputUri.");
|
| - completer.complete(event['.js']);
|
| - setContentType(outputUri.path);
|
| - response.write(event['.js']);
|
| - response.close();
|
| - }
|
| - });
|
| - }
|
| -
|
| - onCompilerEvent(Completer completer, CompilerEvent event) {
|
| - Uri outputUri = request.uri;
|
| - print("Got ${event.kind} for $outputUri");
|
| -
|
| - switch (event.kind) {
|
| - case IncrementalKind.FULL:
|
| - generatedFiles[outputUri] = new Future.value(event['.js']);
|
| - break;
|
| -
|
| - case IncrementalKind.INCREMENTAL:
|
| - generatedFiles[outputUri] = completer.future.then(
|
| - (String full) => '$full\n\n${event.compiler.allUpdates()}');
|
| - pushUpdates(event.updates);
|
| - break;
|
| -
|
| - case IncrementalKind.ERROR:
|
| - generatedFiles.removeKey(outputUri);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - void pushUpdates(String updates) {
|
| - if (updates == null) return;
|
| - StreamController<String> controller = updateControllers[request.uri];
|
| - if (controller == null) return;
|
| - print("Adding updates to controller");
|
| - controller.add(updates);
|
| - }
|
| -
|
| - Future dispatch() async {
|
| - try {
|
| - return await WebSocketTransformer.isUpgradeRequest(request)
|
| - ? handleSocket()
|
| - : handle();
|
| - } catch (e, s) {
|
| - onError(e, s);
|
| - }
|
| - }
|
| -
|
| - static Future onRequest(HttpRequest request) async {
|
| - HttpResponse response = request.response;
|
| - try {
|
| - return await new Conversation(request, response).dispatch();
|
| - } catch (e, s) {
|
| - try {
|
| - onStaticError(e, s);
|
| - return await response.close();
|
| - } catch (e, s) {
|
| - onStaticError(e, s);
|
| - }
|
| - }
|
| - }
|
| -
|
| - Future onError(error, [stack]) async {
|
| - try {
|
| - onStaticError(error, stack);
|
| - return await response.close();
|
| - } catch (e, s) {
|
| - onStaticError(e, s);
|
| - }
|
| - }
|
| -
|
| - static void onStaticError(error, [stack]) {
|
| - if (error is HttpException) {
|
| - print('Error: ${error.message}');
|
| - } else {
|
| - print('Error: ${error}');
|
| - }
|
| - if (stack != null) {
|
| - print(stack);
|
| - }
|
| - }
|
| -
|
| - String htmlInfo(String title, String text) {
|
| - // No script injection, please.
|
| - title = const HtmlEscape().convert(title);
|
| - text = const HtmlEscape().convert(text);
|
| - return """
|
| -<!DOCTYPE html>
|
| -<html lang='en'>
|
| -<head>
|
| -<title>$title</title>
|
| -</head>
|
| -<body>
|
| -<h1>$title</h1>
|
| -<p style='white-space:pre'>$text</p>
|
| -</body>
|
| -</html>
|
| -""";
|
| - }
|
| -}
|
| -
|
| -main(List<String> arguments) async {
|
| - Options options = Options.parse(arguments);
|
| - if (options == null) {
|
| - exit(1);
|
| - }
|
| - if (!options.arguments.isEmpty) {
|
| - Conversation.documentRoot = Uri.base.resolve(options.arguments.single);
|
| - }
|
| - Conversation.packageRoot = options.packageRoot;
|
| - String host = options.host;
|
| - int port = options.port;
|
| - try {
|
| - HttpServer server = await HttpServer.bind(host, port);
|
| - print('HTTP server started on http://$host:${server.port}/');
|
| - server.listen(Conversation.onRequest, onError: Conversation.onStaticError);
|
| - } catch (e) {
|
| - print("HttpServer.bind error: $e");
|
| - exit(1);
|
| - };
|
| -}
|
|
|