Send console messages through interaction manager.

R=johnniwinther@google.com

Review URL: https://codereview.chromium.org//340343006

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@37602 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ahe@google.com 2014-06-23 15:19:50 +00:00
parent 01bddd1c9c
commit bd73f1ad63
3 changed files with 118 additions and 43 deletions

View file

@ -71,7 +71,6 @@ class CompilationProcess {
final Element console;
final ReceivePort receivePort = new ReceivePort();
final Set<String> seenMessages = new Set<String>();
bool isCleared = false;
bool isDone = false;
bool usesDartHtml = false;
Worker worker;
@ -88,12 +87,6 @@ class CompilationProcess {
return true;
}
void clear() {
if (verboseCompiler) return;
if (!isCleared) console.nodes.clear();
isCleared = true;
}
void start() {
if (!shouldStartCompilation()) {
receivePort.close();
@ -101,7 +94,6 @@ class CompilationProcess {
}
if (current != null) current.dispose();
current = this;
console.nodes.clear();
var options = [
'--analyze-main',
'--disable-type-inference',
@ -113,9 +105,6 @@ class CompilationProcess {
if (onlyAnalyze) options.add('--analyze-only');
interaction.compilationStarting();
compilerPort.send([['options', options], receivePort.sendPort]);
console.appendHtml('<i class="icon-spinner icon-spin"></i>');
console.appendText(' Compiling Dart program...\n');
outputFrame.style.display = 'none';
receivePort.listen(onMessage);
compilerPort.send([source, receivePort.sendPort]);
}
@ -146,8 +135,8 @@ class CompilationProcess {
}
onFail(_) {
clear();
consolePrint('Compilation failed');
// TODO(ahe): Call interaction.onCompilationFailed().
interaction.consolePrintLine('Compilation failed');
}
onDone(_) {
@ -160,7 +149,6 @@ class CompilationProcess {
// web worker. For example, Chrome and Firefox 21.
onUrl(String url) {
objectUrls.add(url);
clear();
String wrapper = '''
// Fool isolate_helper.dart so it does not think this is an isolate.
var window = self;
@ -194,8 +182,6 @@ self.importScripts("$url");
// This is called in browsers that do not support creating Object
// URLs in a web worker. For example, Safari and Firefox < 21.
onCode(String code) {
clear();
void retryInIframe(_) {
// The obvious thing would be to call [makeOutputFrame], but
// Safari doesn't support access to Object URLs in an iframe.
@ -236,7 +222,7 @@ self.importScripts("$url");
void runInWorker(String url, void onError(String errorMessage)) {
worker = new Worker(url)
..onMessage.listen((MessageEvent event) {
consolePrint(event.data);
interaction.consolePrintLine(event.data);
})
..onError.listen((ErrorEvent event) {
worker.terminate();
@ -250,16 +236,12 @@ self.importScripts("$url");
String kind = diagnostic['kind'];
String message = diagnostic['message'];
if (kind == 'verbose info') {
if (verboseCompiler) {
consolePrint(message);
} else {
console.appendText('.');
}
interaction.verboseCompilerMessage(message);
return;
}
String uri = diagnostic['uri'];
if (uri != '${PRIVATE_SCHEME}:/main.dart') {
consolePrint('$uri: [$kind] $message');
interaction.consolePrintLine('$uri: [$kind] $message');
return;
}
int begin = diagnostic['begin'];
@ -272,17 +254,6 @@ self.importScripts("$url");
}
onCrash(data) {
consolePrint(data);
}
void consolePrint(message) {
if (window.parent != window) {
// Test support.
// TODO(ahe): Use '/' instead of '*' when Firefox is upgraded to version
// 30 across build bots. Support for '/' was added in version 29, and we
// support the two most recent versions.
window.parent.postMessage('$message\n', '*');
}
console.appendText('$message\n');
interaction.consolePrintLine(data);
}
}

View file

@ -80,12 +80,23 @@ const String TRY_DART_NEW_DEFECT =
'https://code.google.com/p/dart/issues/entry'
'?template=Try+Dart+Internal+Error';
const Duration HEARTBEAT_INTERVAL = const Duration(milliseconds: 500);
/// How frequently [InteractionManager.onHeartbeat] is called.
const Duration HEARTBEAT_INTERVAL = const Duration(milliseconds: 50);
/// Determines how frequently "project" files are saved. The time is measured
/// from the time of last modification.
const Duration SAVE_INTERVAL = const Duration(seconds: 5);
/// Determines how frequently the compiler is invoked. The time is measured
/// from the time of last modification.
const Duration COMPILE_INTERVAL = const Duration(seconds: 1);
/// Determines if a compilation is slow. The time is measured from the last
/// compilation started. If a compilation is slow, progress information is
/// displayed to the user, but the console is untouched if the compilation
/// finished quickly. The purpose is to reduce flicker in the UI.
const Duration SLOW_COMPILE = const Duration(seconds: 1);
/**
* UI interaction manager for the entire application.
*/
@ -132,17 +143,24 @@ abstract class InteractionManager {
/// Called when notified about a project file changed (on the server).
void onProjectFileFsEvent(MessageEvent e);
/// Called every 500ms.
/// Called every [HEARTBEAT_INTERVAL].
void onHeartbeat(Timer timer);
/// Called by [:window.onMessage.listen:].
void onMessage(MessageEvent event);
void onWindowMessage(MessageEvent event);
void onCompilationFailed();
void onCompilationDone();
/// Called when a compilation is starting, but just before sending the
/// initiating message to the compiler isolate.
void compilationStarting();
// TODO(ahe): Remove this from InteractionManager, but not from InitialState.
void consolePrintLine(line);
void verboseCompilerMessage(String message);
}
/**
@ -157,10 +175,15 @@ class InteractionContext extends InteractionManager {
final Queue<CompilationUnit> unitsToSave = new Queue<CompilationUnit>();
/// Tracks time since last modification of a "project" file.
final Stopwatch saveTimer = new Stopwatch();
/// Tracks time since last modification.
final Stopwatch compileTimer = new Stopwatch();
/// Tracks elapsed time of current compilation.
final Stopwatch elapsedCompilationTime = new Stopwatch();
CompilationUnit currentCompilationUnit =
// TODO(ahe): Don't use a fake unit.
new CompilationUnit('fake', '');
@ -169,6 +192,12 @@ class InteractionContext extends InteractionManager {
Completer<String> completeSaveOperation;
bool shouldClearConsole = false;
Element compilerConsole;
bool isFirstCompile = true;
final Set<AnchorElement> oldDiagnostics = new Set<AnchorElement>();
InteractionContext()
@ -229,11 +258,19 @@ class InteractionContext extends InteractionManager {
void onHeartbeat(Timer timer) => state.onHeartbeat(timer);
void onMessage(MessageEvent event) => state.onMessage(event);
void onWindowMessage(MessageEvent event) => state.onWindowMessage(event);
void onCompilationFailed() => state.onCompilationFailed();
void onCompilationDone() => state.onCompilationDone();
void compilationStarting() => state.compilationStarting();
void consolePrintLine(line) => state.consolePrintLine(line);
void verboseCompilerMessage(String message) {
return state.verboseCompilerMessage(message);
}
}
abstract class InteractionState implements InteractionManager {
@ -526,6 +563,12 @@ class InitialState extends InteractionState {
..reset();
}
}
if (context.elapsedCompilationTime.elapsed > SLOW_COMPILE) {
if (context.compilerConsole.parent == null) {
outputDiv.append(context.compilerConsole);
}
}
}
void saveUnits() {
@ -554,7 +597,7 @@ class InitialState extends InteractionState {
setupCompleter();
}
void onMessage(MessageEvent event) {
void onWindowMessage(MessageEvent event) {
if (event.source is! WindowBase || event.source == window) {
return onBadMessage(event);
}
@ -601,11 +644,33 @@ class InitialState extends InteractionState {
..groupEnd();
}
void consolePrintLine(data) {
outputDiv.appendText('$data\n');
void consolePrintLine(line) {
if (context.shouldClearConsole) {
context.shouldClearConsole = false;
outputDiv.nodes.clear();
}
if (window.parent != window) {
// Test support.
// TODO(ahe): Use '/' instead of '*' when Firefox is upgraded to version
// 30 across build bots. Support for '/' was added in version 29, and we
// support the two most recent versions.
window.parent.postMessage('$line\n', '*');
}
outputDiv.appendText('$line\n');
}
void onCompilationFailed() {
}
void onCompilationDone() {
context.isFirstCompile = false;
context.elapsedCompilationTime.stop();
Duration compilationDuration = context.elapsedCompilationTime.elapsed;
context.elapsedCompilationTime.reset();
print('Compilation took $compilationDuration.');
if (context.compilerConsole.parent != null) {
context.compilerConsole.remove();
}
for (AnchorElement diagnostic in context.oldDiagnostics) {
if (diagnostic.parent != null) {
// Problem fixed, remove the diagnostic.
@ -617,10 +682,37 @@ class InitialState extends InteractionState {
}
void compilationStarting() {
var progress = new SpanElement()
..appendHtml('<i class="icon-spinner icon-spin"></i>')
..appendText(' Compiling Dart program.');
if (settings.verboseCompiler) {
progress.appendText('..');
}
context.compilerConsole = new SpanElement()
..append(progress)
..appendText('\n');
context.shouldClearConsole = true;
context.elapsedCompilationTime
..start()
..reset();
if (context.isFirstCompile) {
outputDiv.append(context.compilerConsole);
}
context.oldDiagnostics
..clear()
..addAll(mainEditorPane.querySelectorAll('a.diagnostic'));
}
void verboseCompilerMessage(String message) {
if (settings.verboseCompiler) {
context.compilerConsole.appendText('$message\n');
} else {
if (isCompilerStageMarker(message)) {
Element progress = context.compilerConsole.firstChild;
progress.appendText('.');
}
}
}
}
Future<String> getString(uri) {
@ -1070,3 +1162,14 @@ void removeCodeCompletion() {
element.remove();
}
}
bool isCompilerStageMarker(String message) {
return
message.startsWith('Package root is ') ||
message.startsWith('Compiling ') ||
message == "Resolving..." ||
message.startsWith('Resolved ') ||
message == "Inferring types..." ||
message == "Compiling..." ||
message.startsWith('Compiled ');
}

View file

@ -92,6 +92,7 @@ void onCodeChange(Event event) {
Function action = codeCallbacks[id];
if (action != null) action(event);
outputFrame.style.display = 'none';
outputDiv.nodes.clear();
}
buildUI() {
@ -198,7 +199,7 @@ buildUI() {
var settingsElement = document.getElementById('settings');
settingsElement.onClick.listen(openSettings);
window.onMessage.listen(interaction.onMessage);
window.onMessage.listen(interaction.onWindowMessage);
observer = new MutationObserver(interaction.onMutation)
..observe(