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

Unified Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 2312553002: Converted Observatory debugger elements (Closed)
Patch Set: Sharing command history and console Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/src/elements/debugger.dart
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 9bd4eff7468217b95756ca696146adbd41629e3b..3f7d8191ce4db3a68263f64f4f52b258ba6ad1c2 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -5,17 +5,30 @@
library debugger_page_element;
import 'dart:async';
+import 'dart:svg';
import 'dart:html';
import 'dart:math';
-import 'observatory_element.dart';
import 'package:observatory/event.dart';
import 'package:observatory/models.dart' as M;
import 'package:observatory/app.dart';
import 'package:observatory/cli.dart';
import 'package:observatory/debugger.dart';
-import 'package:observatory/service.dart';
+import 'package:observatory/src/elements/function_ref.dart';
+import 'package:observatory/src/elements/helpers/any_ref.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/instance_ref.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+import 'package:observatory/src/elements/source_inset.dart';
+import 'package:observatory/src/elements/source_link.dart';
+import 'package:observatory/service.dart' as S;
import 'package:logging/logging.dart';
-import 'package:polymer/polymer.dart';
// TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
abstract class DebuggerCommand extends Command {
@@ -161,11 +174,11 @@ class PrintCommand extends DebuggerCommand {
var expression = args.join('');
var response = await debugger.isolate.evalFrame(debugger.currentFrame,
expression);
- if (response is DartError) {
+ if (response is S.DartError) {
debugger.console.print(response.message);
} else {
debugger.console.print('= ', newline:false);
- debugger.console.printRef(response);
+ debugger.console.printRef(debugger.isolate, response, debugger.instances);
}
}
@@ -648,8 +661,8 @@ class BreakCommand extends DebuggerCommand {
if (loc.function != null) {
try {
await debugger.isolate.addBreakpointAtEntry(loc.function);
- } on ServerRpcException catch(e) {
- if (e.code == ServerRpcException.kCannotAddBreakpoint) {
+ } on S.ServerRpcException catch(e) {
+ if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
debugger.console.print('Unable to set breakpoint at ${loc}');
} else {
rethrow;
@@ -666,8 +679,8 @@ class BreakCommand extends DebuggerCommand {
}
try {
await debugger.isolate.addBreakpoint(script, loc.line, loc.col);
- } on ServerRpcException catch(e) {
- if (e.code == ServerRpcException.kCannotAddBreakpoint) {
+ } on S.ServerRpcException catch(e) {
+ if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
debugger.console.print('Unable to set breakpoint at ${loc}');
} else {
rethrow;
@@ -756,7 +769,7 @@ class ClearCommand extends DebuggerCommand {
loc.col == script.tokenToCol(bpt.location.tokenPos)) {
foundBreakpoint = true;
var result = await debugger.isolate.removeBreakpoint(bpt);
- if (result is DartError) {
+ if (result is S.DartError) {
debugger.console.print(
'Error clearing breakpoint ${bpt.number}: ${result.message}');
}
@@ -938,9 +951,7 @@ class IsolateCommand extends DebuggerCommand {
debugger.console.print(
"Current isolate is already ${candidate.number} '${candidate.name}'");
} else {
- debugger.console.print(
- "Switching to isolate ${candidate.number} '${candidate.name}'");
- debugger.isolate = candidate;
+ new AnchorElement(href: Uris.debugger(candidate)).click();
}
}
return new Future.value(null);
@@ -973,7 +984,7 @@ class IsolateCommand extends DebuggerCommand {
' isolate <name>\n';
}
-String _isolateRunState(Isolate isolate) {
+String _isolateRunState(S.Isolate isolate) {
if (isolate.paused) {
return 'paused';
} else if (isolate.running) {
@@ -1248,8 +1259,8 @@ class _ConsoleStreamPrinter {
String _savedLine;
List<String> _buffer = [];
- void onEvent(String streamName, ServiceEvent event) {
- if (event.kind == ServiceEvent.kLogging) {
+ void onEvent(String streamName, S.ServiceEvent event) {
+ if (event.kind == S.ServiceEvent.kLogging) {
// Check if we should print this log message.
if (event.logRecord['level'].value < _minimumLogLevel.value) {
return;
@@ -1264,7 +1275,7 @@ class _ConsoleStreamPrinter {
}
String data;
bool hasNewline;
- if (event.kind == ServiceEvent.kLogging) {
+ if (event.kind == S.ServiceEvent.kLogging) {
data = event.logRecord["message"].valueAsString;
hasNewline = true;
} else {
@@ -1320,7 +1331,8 @@ class ObservatoryDebugger extends Debugger {
DebuggerConsoleElement console;
DebuggerInputElement input;
DebuggerStackElement stackElement;
- ServiceMap stack;
+ S.ServiceMap stack;
+ final S.Isolate isolate;
String breakOnException = "none"; // Last known setting.
int get currentFrame => _currentFrame;
@@ -1361,7 +1373,9 @@ class ObservatoryDebugger extends Debugger {
int get stackDepth => stack['frames'].length;
- ObservatoryDebugger() {
+ static final _history = [''];
+
+ ObservatoryDebugger(this.isolate) {
_loadSettings();
cmd = new RootCommand([
new AsyncNextCommand(this),
@@ -1386,7 +1400,7 @@ class ObservatoryDebugger extends Debugger {
new SyncNextCommand(this),
new UpCommand(this),
new VmCommand(this),
- ]);
+ ], _history);
_consolePrinter = new _ConsoleStreamPrinter(this);
}
@@ -1394,55 +1408,12 @@ class ObservatoryDebugger extends Debugger {
_upIsDown = settings.get('up-is-down');
}
- VM get vm => page.app.vm;
-
- void updateIsolate(Isolate iso) {
- _isolate = iso;
- if (_isolate != null) {
- if ((breakOnException != iso.exceptionsPauseInfo) &&
- (iso.exceptionsPauseInfo != null)) {
- breakOnException = iso.exceptionsPauseInfo;
- }
-
- _isolate.reload().then((response) {
- if (response.isSentinel) {
- // The isolate has gone away. The IsolateExit event will
- // clear the isolate for the debugger page.
- return;
- }
- // TODO(turnidge): Currently the debugger relies on all libs
- // being loaded. Fix this.
- var pending = [];
- for (var lib in response.libraries) {
- if (!lib.loaded) {
- pending.add(lib.load());
- }
- }
- Future.wait(pending).then((_) {
- refreshStack();
- }).catchError((e) {
- print("UNEXPECTED ERROR $e");
- reportStatus();
- });
- });
- } else {
- reportStatus();
- }
- }
-
- set isolate(Isolate iso) {
- // Setting the page's isolate will trigger updateIsolate to be called.
- //
- // TODO(turnidge): Rework ownership of the ObservatoryDebugger in another
- // change.
- page.isolate = iso;
- }
- Isolate get isolate => _isolate;
- Isolate _isolate;
+ S.VM get vm => page.app.vm;
void init() {
- console.newline();
- console.printBold("Type 'h' for help");
+ console.printBold('Debugging isolate isolate ${isolate.number} '
+ '\'${isolate.name}\' ');
+ console.printBold('Type \'h\' for help');
// Wait a bit and if polymer still hasn't set up the isolate,
// report this to the user.
new Timer(const Duration(seconds:1), () {
@@ -1450,12 +1421,39 @@ class ObservatoryDebugger extends Debugger {
reportStatus();
}
});
+
+ if ((breakOnException != isolate.exceptionsPauseInfo) &&
+ (isolate.exceptionsPauseInfo != null)) {
+ breakOnException = isolate.exceptionsPauseInfo;
+ }
+
+ isolate.reload().then((response) {
+ if (response.isSentinel) {
+ // The isolate has gone away. The IsolateExit event will
+ // clear the isolate for the debugger page.
+ return;
+ }
+ // TODO(turnidge): Currently the debugger relies on all libs
+ // being loaded. Fix this.
+ var pending = [];
+ for (var lib in response.libraries) {
+ if (!lib.loaded) {
+ pending.add(lib.load());
+ }
+ }
+ Future.wait(pending).then((_) {
+ refreshStack();
+ }).catchError((e) {
+ print("UNEXPECTED ERROR $e");
+ reportStatus();
+ });
+ });
}
Future refreshStack() async {
try {
- if (_isolate != null) {
- await _refreshStack(_isolate.pauseEvent);
+ if (isolate != null) {
+ await _refreshStack(isolate.pauseEvent);
}
flushStdio();
reportStatus();
@@ -1468,9 +1466,7 @@ class ObservatoryDebugger extends Debugger {
// TODO(turnidge): Stop relying on the isolate to track the last
// pause event. Since we listen to events directly in the
// debugger, this could introduce a race.
- return (isolate != null &&
- isolate.pauseEvent != null &&
- isolate.pauseEvent is M.ResumeEvent);
+ return isolate.status == M.IsolateStatus.paused;
}
void warnOutOfDate() {
@@ -1482,7 +1478,7 @@ class ObservatoryDebugger extends Debugger {
});
}
- Future<ServiceMap> _refreshStack(M.DebugEvent pauseEvent) {
+ Future<S.ServiceMap> _refreshStack(M.DebugEvent pauseEvent) {
return isolate.getStack().then((result) {
if (result.isSentinel) {
// The isolate has gone away. The IsolateExit event will
@@ -1502,25 +1498,25 @@ class ObservatoryDebugger extends Debugger {
void reportStatus() {
flushStdio();
- if (_isolate == null) {
+ if (isolate == null) {
console.print('No current isolate');
- } else if (_isolate.idle) {
+ } else if (isolate.idle) {
console.print('Isolate is idle');
- } else if (_isolate.running) {
+ } else if (isolate.running) {
console.print("Isolate is running (type 'pause' to interrupt)");
- } else if (_isolate.pauseEvent != null) {
- _reportPause(_isolate.pauseEvent);
+ } else if (isolate.pauseEvent != null) {
+ _reportPause(isolate.pauseEvent);
} else {
console.print('Isolate is in unknown state');
}
warnOutOfDate();
}
- void _reportIsolateError(Isolate isolate, M.DebugEvent event) {
+ void _reportIsolateError(S.Isolate isolate, M.DebugEvent event) {
if (isolate == null) {
return;
}
- DartError error = isolate.error;
+ S.DartError error = isolate.error;
if (error == null) {
return;
}
@@ -1565,7 +1561,7 @@ class ObservatoryDebugger extends Debugger {
"(type 'continue' or [F7] to exit the isolate')");
_reportIsolateError(isolate, event);
} else if (stack['frames'].length > 0) {
- Frame frame = stack['frames'][0];
+ S.Frame frame = stack['frames'][0];
var script = frame.location.script;
script.load().then((_) {
var line = script.tokenToLine(frame.location.tokenPos);
@@ -1582,7 +1578,7 @@ class ObservatoryDebugger extends Debugger {
// This seems to be missing if we are paused-at-exception after
// paused-at-isolate-exit. Maybe we shutdown part of the debugger too
// soon?
- console.printRef(event.exception);
+ console.printRef(isolate, event.exception, instances);
} else {
console.print('Paused at ${script.name}:${line}:${col}');
}
@@ -1593,17 +1589,17 @@ class ObservatoryDebugger extends Debugger {
}
}
- Future _reportBreakpointEvent(ServiceEvent event) async {
+ Future _reportBreakpointEvent(S.ServiceEvent event) async {
var bpt = event.breakpoint;
var verb = null;
switch (event.kind) {
- case ServiceEvent.kBreakpointAdded:
+ case S.ServiceEvent.kBreakpointAdded:
verb = 'added';
break;
- case ServiceEvent.kBreakpointResolved:
+ case S.ServiceEvent.kBreakpointResolved:
verb = 'resolved';
break;
- case ServiceEvent.kBreakpointRemoved:
+ case S.ServiceEvent.kBreakpointRemoved:
verb = 'removed';
break;
default:
@@ -1623,26 +1619,22 @@ class ObservatoryDebugger extends Debugger {
}
}
- void onEvent(ServiceEvent event) {
+ void onEvent(S.ServiceEvent event) {
switch(event.kind) {
- case ServiceEvent.kVMUpdate:
+ case S.ServiceEvent.kVMUpdate:
var vm = event.owner;
console.print("VM ${vm.target.networkAddress} renamed to '${vm.name}'");
break;
- case ServiceEvent.kIsolateStart:
+ case S.ServiceEvent.kIsolateStart:
{
var iso = event.owner;
console.print(
"Isolate ${iso.number} '${iso.name}' has been created");
- if (isolate == null) {
- console.print("Switching to isolate ${iso.number} '${iso.name}'");
- isolate = iso;
- }
}
break;
- case ServiceEvent.kIsolateExit:
+ case S.ServiceEvent.kIsolateExit:
{
var iso = event.owner;
if (iso == isolate) {
@@ -1651,11 +1643,9 @@ class ObservatoryDebugger extends Debugger {
var isolates = vm.isolates;
if (isolates.length > 0) {
var newIsolate = isolates.first;
- console.print("Switching to isolate "
- "${newIsolate.number} '${newIsolate.name}'");
- isolate = newIsolate;
+ new AnchorElement(href: Uris.debugger(newIsolate)).click();
} else {
- isolate = null;
+ new AnchorElement(href: Uris.vm()).click();
}
} else {
console.print(
@@ -1664,19 +1654,19 @@ class ObservatoryDebugger extends Debugger {
}
break;
- case ServiceEvent.kDebuggerSettingsUpdate:
+ case S.ServiceEvent.kDebuggerSettingsUpdate:
if (breakOnException != event.exceptions) {
breakOnException = event.exceptions;
console.print("Now pausing for exceptions: $breakOnException");
}
break;
- case ServiceEvent.kIsolateUpdate:
+ case S.ServiceEvent.kIsolateUpdate:
var iso = event.owner;
console.print("Isolate ${iso.number} renamed to '${iso.name}'");
break;
- case ServiceEvent.kIsolateReload:
+ case S.ServiceEvent.kIsolateReload:
var reloadError = event.reloadError;
if (reloadError != null) {
console.print('Isolate reload failed: ${event.reloadError}');
@@ -1685,11 +1675,11 @@ class ObservatoryDebugger extends Debugger {
}
break;
- case ServiceEvent.kPauseStart:
- case ServiceEvent.kPauseExit:
- case ServiceEvent.kPauseBreakpoint:
- case ServiceEvent.kPauseInterrupted:
- case ServiceEvent.kPauseException:
+ case S.ServiceEvent.kPauseStart:
+ case S.ServiceEvent.kPauseExit:
+ case S.ServiceEvent.kPauseBreakpoint:
+ case S.ServiceEvent.kPauseInterrupted:
+ case S.ServiceEvent.kPauseException:
if (event.owner == isolate) {
var e = createEventFromServiceEvent(event);
_refreshStack(e).then((_) async {
@@ -1702,29 +1692,29 @@ class ObservatoryDebugger extends Debugger {
}
break;
- case ServiceEvent.kResume:
+ case S.ServiceEvent.kResume:
if (event.owner == isolate) {
flushStdio();
console.print('Continuing...');
}
break;
- case ServiceEvent.kBreakpointAdded:
- case ServiceEvent.kBreakpointResolved:
- case ServiceEvent.kBreakpointRemoved:
+ case S.ServiceEvent.kBreakpointAdded:
+ case S.ServiceEvent.kBreakpointResolved:
+ case S.ServiceEvent.kBreakpointRemoved:
if (event.owner == isolate) {
_reportBreakpointEvent(event);
}
break;
- case ServiceEvent.kIsolateRunnable:
- case ServiceEvent.kGraph:
- case ServiceEvent.kGC:
- case ServiceEvent.kInspect:
+ case S.ServiceEvent.kIsolateRunnable:
+ case S.ServiceEvent.kGraph:
+ case S.ServiceEvent.kGC:
+ case S.ServiceEvent.kInspect:
// Ignore.
break;
- case ServiceEvent.kLogging:
+ case S.ServiceEvent.kLogging:
_consolePrinter.onEvent(event.logRecord['level'].name, event);
break;
@@ -1740,11 +1730,11 @@ class ObservatoryDebugger extends Debugger {
_consolePrinter.flush();
}
- void onStdout(ServiceEvent event) {
+ void onStdout(S.ServiceEvent event) {
_consolePrinter.onEvent('stdout', event);
}
- void onStderr(ServiceEvent event) {
+ void onStderr(S.ServiceEvent event) {
_consolePrinter.onEvent('stderr', event);
}
@@ -1798,7 +1788,7 @@ class ObservatoryDebugger extends Debugger {
return cmd.runCommand(command).then((_) {
lastCommand = command;
}).catchError((e, s) {
- if (e is NetworkRpcException) {
+ if (e is S.NetworkRpcException) {
console.printRed('Unable to execute command because the connection '
'to the VM has been closed');
} else {
@@ -1921,20 +1911,44 @@ class ObservatoryDebugger extends Debugger {
}
}
-@CustomTag('debugger-page')
-class DebuggerPageElement extends ObservatoryElement {
- @published Isolate isolate;
-
- isolateChanged(oldValue) {
- debugger.updateIsolate(isolate);
- }
- ObservatoryDebugger debugger = new ObservatoryDebugger();
-
- DebuggerPageElement.created() : super.created() {
- debugger.page = this;
- }
+class DebuggerPageElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerPageElement>('debugger-page',
+ dependencies: const [
+ NavBarElement.tag,
+ NavTopMenuElement.tag,
+ NavVMMenuElement.tag,
+ NavIsolateMenuElement.tag,
+ NavMenuElement.tag,
+ NavNotifyElement.tag,
+ ]);
+
+ S.Isolate _isolate;
+ ObservatoryDebugger _debugger;
+ M.InstanceRepository _instances;
+ M.ScriptRepository _scripts;
+ M.EventRepository _events;
+
+ factory DebuggerPageElement(S.Isolate isolate,
+ M.InstanceRepository instances,
+ M.ScriptRepository scripts,
+ M.EventRepository events) {
+ assert(isolate != null);
+ assert(instances != null);
+ assert(scripts != null);
+ assert(events != null);
+ final e = document.createElement(tag.name);
+ final debugger = new ObservatoryDebugger(isolate);
+ debugger.page = e;
+ e._isolate = isolate;
+ e._debugger = debugger;
+ e._instances = instances;
+ e._scripts = scripts;
+ e._events = events;
+ return e;
+ }
+
+ DebuggerPageElement.created() : super.created();
- StreamSubscription _resizeSubscription;
Future<StreamSubscription> _vmSubscriptionFuture;
Future<StreamSubscription> _isolateSubscriptionFuture;
Future<StreamSubscription> _debugSubscriptionFuture;
@@ -1942,30 +1956,66 @@ class DebuggerPageElement extends ObservatoryElement {
Future<StreamSubscription> _stderrSubscriptionFuture;
Future<StreamSubscription> _logSubscriptionFuture;
+ ObservatoryApplication get app => ObservatoryApplication.app;
+
+ Timer _timer;
+
+ static final consoleElement = new DebuggerConsoleElement();
+
@override
void attached() {
super.attached();
- _onResize(null);
+
+ final stackDiv = new DivElement()..classes = ['stack'];
+ final stackElement = new DebuggerStackElement(_isolate, _debugger, stackDiv,
+ _instances, _scripts,
+ _events);
+ stackDiv.children = [stackElement];
+ final consoleDiv = new DivElement()..classes = ['console']
+ ..children = [consoleElement];
+ final commandElement = new DebuggerInputElement(_isolate, _debugger);
+ final commandDiv = new DivElement()..classes = ['commandline']
+ ..children = [commandElement];
+
+ children = [
+ new NavBarElement(queue: app.queue)
+ ..children = [
+ new NavTopMenuElement(queue: app.queue),
+ new NavVMMenuElement(app.vm, app.events, queue: app.queue),
+ new NavIsolateMenuElement(_isolate, app.events, queue: app.queue),
+ new NavMenuElement('debugger', last: true, queue: app.queue),
+ new NavNotifyElement(app.notifications, notifyOnPause: false,
+ queue: app.queue)
+ ],
+ new DivElement()..classes = ['variable']
+ ..children = [
+ stackDiv,
+ new DivElement()
+ ..children = [
+ new HRElement()..classes = ['splitter']
+ ],
+ consoleDiv,
+ ],
+ commandDiv
+ ];
+
+ DebuggerConsoleElement._scrollToBottom(consoleDiv);
// Wire the debugger object to the stack, console, and command line.
- var stackElement = $['stackElement'];
- debugger.stackElement = stackElement;
- stackElement.debugger = debugger;
- stackElement.scroller = $['stackDiv'];
- debugger.console = $['console'];
- debugger.input = $['commandline'];
- debugger.input.debugger = debugger;
- debugger.init();
-
- _resizeSubscription = window.onResize.listen(_onResize);
+ _debugger.stackElement = stackElement;
+ _debugger.console = consoleElement;
+ _debugger.input = commandElement;
+ _debugger.input._debugger = _debugger;
+ _debugger.init();
+
_vmSubscriptionFuture =
- app.vm.listenEventStream(VM.kVMStream, debugger.onEvent);
+ app.vm.listenEventStream(S.VM.kVMStream, _debugger.onEvent);
_isolateSubscriptionFuture =
- app.vm.listenEventStream(VM.kIsolateStream, debugger.onEvent);
+ app.vm.listenEventStream(S.VM.kIsolateStream, _debugger.onEvent);
_debugSubscriptionFuture =
- app.vm.listenEventStream(VM.kDebugStream, debugger.onEvent);
+ app.vm.listenEventStream(S.VM.kDebugStream, _debugger.onEvent);
_stdoutSubscriptionFuture =
- app.vm.listenEventStream(VM.kStdoutStream, debugger.onStdout);
+ app.vm.listenEventStream(S.VM.kStdoutStream, _debugger.onStdout);
if (_stdoutSubscriptionFuture != null) {
// TODO(turnidge): How do we want to handle this in general?
_stdoutSubscriptionFuture.catchError((e, st) {
@@ -1974,7 +2024,7 @@ class DebuggerPageElement extends ObservatoryElement {
});
}
_stderrSubscriptionFuture =
- app.vm.listenEventStream(VM.kStderrStream, debugger.onStderr);
+ app.vm.listenEventStream(S.VM.kStderrStream, _debugger.onStderr);
if (_stderrSubscriptionFuture != null) {
// TODO(turnidge): How do we want to handle this in general?
_stderrSubscriptionFuture.catchError((e, st) {
@@ -1983,9 +2033,11 @@ class DebuggerPageElement extends ObservatoryElement {
});
}
_logSubscriptionFuture =
- app.vm.listenEventStream(Isolate.kLoggingStream, debugger.onEvent);
+ app.vm.listenEventStream(S.Isolate.kLoggingStream, _debugger.onEvent);
// Turn on the periodic poll timer for this page.
- pollPeriod = const Duration(milliseconds:100);
+ _timer = new Timer.periodic(const Duration(milliseconds:100), (_) {
+ _debugger.flushStdio();
+ });
onClick.listen((event) {
// Random clicks should focus on the text box. If the user selects
@@ -1993,70 +2045,140 @@ class DebuggerPageElement extends ObservatoryElement {
var selection = window.getSelection();
if (selection == null ||
(selection.type != 'Range' && selection.type != 'text')) {
- debugger.input.focus();
+ _debugger.input.focus();
}
});
}
- void onPoll() {
- debugger.flushStdio();
- }
-
- void _onResize(_) {
- var navbarDiv = $['navbarDiv'];
- var stackDiv = $['stackDiv'];
- var splitterDiv = $['splitterDiv'];
- var cmdDiv = $['commandDiv'];
-
- // For now, force navbar height to 40px in the debugger.
- // TODO (cbernaschina) check if this is needed.
- const navbarHeight = 40;
- int splitterHeight = splitterDiv.clientHeight;
- int cmdHeight = cmdDiv.clientHeight;
-
- int windowHeight = window.innerHeight;
- int fixedHeight = navbarHeight + splitterHeight + cmdHeight;
- int available = windowHeight - fixedHeight;
- int stackHeight = available ~/ 1.6;
- navbarDiv.style.setProperty('height', '${navbarHeight}px');
- stackDiv.style.setProperty('height', '${stackHeight}px');
- }
-
@override
void detached() {
- debugger.isolate = null;
- _resizeSubscription.cancel();
- _resizeSubscription = null;
- cancelFutureSubscription(_vmSubscriptionFuture);
+ _timer.cancel();
+ children = const [];
+ S.cancelFutureSubscription(_vmSubscriptionFuture);
_vmSubscriptionFuture = null;
- cancelFutureSubscription(_isolateSubscriptionFuture);
+ S.cancelFutureSubscription(_isolateSubscriptionFuture);
_isolateSubscriptionFuture = null;
- cancelFutureSubscription(_debugSubscriptionFuture);
+ S.cancelFutureSubscription(_debugSubscriptionFuture);
_debugSubscriptionFuture = null;
- cancelFutureSubscription(_stdoutSubscriptionFuture);
+ S.cancelFutureSubscription(_stdoutSubscriptionFuture);
_stdoutSubscriptionFuture = null;
- cancelFutureSubscription(_stderrSubscriptionFuture);
+ S.cancelFutureSubscription(_stderrSubscriptionFuture);
_stderrSubscriptionFuture = null;
- cancelFutureSubscription(_logSubscriptionFuture);
+ S.cancelFutureSubscription(_logSubscriptionFuture);
_logSubscriptionFuture = null;
super.detached();
}
}
-@CustomTag('debugger-stack')
-class DebuggerStackElement extends ObservatoryElement {
- @published Isolate isolate;
- @published Element scroller;
- @observable bool hasStack = false;
- @observable bool hasMessages = false;
- @observable bool isSampled = false;
- @observable int currentFrame;
- ObservatoryDebugger debugger;
+class DebuggerStackElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerStackElement>('debugger-stack');
- _addFrame(List frameList, Frame frameInfo) {
- DebuggerFrameElement frameElement = new Element.tag('debugger-frame');
- frameElement.frame = frameInfo;
- frameElement.scroller = scroller;
+ S.Isolate _isolate;
+ M.InstanceRepository _instances;
+ M.ScriptRepository _scripts;
+ M.EventRepository _events;
+ Element _scroller;
+ DivElement _isSampled;
+ bool get isSampled => !_isSampled.classes.contains('hidden');
+ set isSampled(bool value) {
+ if (value != isSampled) {
+ _isSampled.classes.toggle('hidden');
+ }
+ }
+ DivElement _hasStack;
+ bool get hasStack => _hasStack.classes.contains('hidden');
+ set hasStack(bool value) {
+ if (value != hasStack) {
+ _hasStack.classes.toggle('hidden');
+ }
+ }
+ DivElement _hasMessages;
+ bool get hasMessages => _hasMessages.classes.contains('hidden');
+ set hasMessages(bool value) {
+ if (value != hasMessages) {
+ _hasMessages.classes.toggle('hidden');
+ }
+ }
+ UListElement _frameList;
+ UListElement _messageList;
+ int currentFrame;
+ ObservatoryDebugger _debugger;
+
+ factory DebuggerStackElement(S.Isolate isolate,
+ ObservatoryDebugger debugger,
+ Element scroller,
+ M.InstanceRepository instances,
+ M.ScriptRepository scripts,
+ M.EventRepository events) {
+ assert(isolate != null);
+ assert(debugger != null);
+ assert(scroller != null);
+ assert(instances != null);
+ assert(scripts != null);
+ assert(events != null);
+ final e = document.createElement(tag.name);
+ e._isolate = isolate;
+ e._debugger = debugger;
+ e._scroller = scroller;
+ e._instances = instances;
+ e._scripts = scripts;
+ e._events = events;
+
+ var btnPause;
+ var btnRefresh;
+ e.children = [
+ e._isSampled = new DivElement()..classes = ['sampledMessage', 'hidden']
+ ..children = [
+ new SpanElement()
+ ..text = 'The program is not paused. '
+ 'The stack trace below may be out of date.',
+ new BRElement(),
+ new BRElement(),
+ btnPause = new ButtonElement()
+ ..text = '[Pause Isolate]'
+ ..onClick.listen((_) async {
+ btnPause.disabled = true;
+ try {
+ await debugger.isolate.pause();
+ }
+ finally {
+ btnPause.disabled = false;
+ }
+ }),
+ btnRefresh = new ButtonElement()
+ ..text = '[Refresh Stack]'
+ ..onClick.listen((_) async {
+ btnRefresh.disabled = true;
+ try {
+ await debugger.refreshStack();
+ }
+ finally {
+ btnRefresh.disabled = false;
+ }
+ }),
+ new BRElement(),
+ new BRElement(),
+ new HRElement()..classes = ['splitter']
+ ],
+ e._hasStack = new DivElement()..classes = ['noStack', 'hidden']
+ ..text = 'No stack',
+ e._frameList = new UListElement()..classes = ['list-group'],
+ new HRElement(),
+ e._hasMessages = new DivElement()..classes = ['noMessages', 'hidden']
+ ..text = 'No pending messages',
+ e._messageList = new UListElement()..classes = ['messageList']
+ ];
+ return e;
+ }
+
+ _addFrame(List frameList, S.Frame frameInfo) {
+ final frameElement = new DebuggerFrameElement(_isolate,
+ frameInfo,
+ _scroller,
+ _instances,
+ _scripts,
+ _events,
+ queue: app.queue);
if (frameInfo.index == currentFrame) {
frameElement.setCurrent(true);
@@ -2071,9 +2193,13 @@ class DebuggerStackElement extends ObservatoryElement {
frameList.insert(0, li);
}
- _addMessage(List messageList, ServiceMessage messageInfo) {
- DebuggerMessageElement messageElement = new Element.tag('debugger-message');
- messageElement.message = messageInfo;
+ _addMessage(List messageList, S.ServiceMessage messageInfo) {
+ final messageElement = new DebuggerMessageElement(_isolate,
+ messageInfo,
+ _instances,
+ _scripts,
+ _events,
+ queue: app.queue);
var li = new LIElement();
li.classes.add('list-group-item');
@@ -2082,8 +2208,10 @@ class DebuggerStackElement extends ObservatoryElement {
messageList.add(li);
}
- void updateStackFrames(ServiceMap newStack) {
- List frameElements = $['frameList'].children;
+ ObservatoryApplication get app => ObservatoryApplication.app;
+
+ void updateStackFrames(S.ServiceMap newStack) {
+ List frameElements = _frameList.children;
List newFrames = newStack['frames'];
// Remove any frames whose functions don't match, starting from
@@ -2132,8 +2260,8 @@ class DebuggerStackElement extends ObservatoryElement {
hasStack = frameElements.isNotEmpty;
}
- void updateStackMessages(ServiceMap newStack) {
- List messageElements = $['messageList'].children;
+ void updateStackMessages(S.ServiceMap newStack) {
+ List messageElements = _messageList.children;
List newMessages = newStack['messages'];
// Remove any extra message elements.
@@ -2157,14 +2285,15 @@ class DebuggerStackElement extends ObservatoryElement {
if (messageElements.isNotEmpty) {
// Update old messages.
for (int i = 0; i < newStartingIndex; i++) {
- messageElements[i].children[0].updateMessage(newMessages[i]);
+ DebuggerMessageElement e = messageElements[i].children[0];
+ e.updateMessage(newMessages[i]);
}
}
hasMessages = messageElements.isNotEmpty;
}
- void updateStack(ServiceMap newStack, M.DebugEvent pauseEvent) {
+ void updateStack(S.ServiceMap newStack, M.DebugEvent pauseEvent) {
updateStackFrames(newStack);
updateStackMessages(newStack);
isSampled = pauseEvent == null;
@@ -2172,9 +2301,9 @@ class DebuggerStackElement extends ObservatoryElement {
void setCurrentFrame(int value) {
currentFrame = value;
- List frameElements = $['frameList'].children;
+ List frameElements = _frameList.children;
for (var frameElement in frameElements) {
- var dbgFrameElement = frameElement.children[0];
+ DebuggerFrameElement dbgFrameElement = frameElement.children[0];
if (dbgFrameElement.frame.index == currentFrame) {
dbgFrameElement.setCurrent(true);
} else {
@@ -2183,29 +2312,24 @@ class DebuggerStackElement extends ObservatoryElement {
}
}
- Future doPauseIsolate() {
- if (debugger != null) {
- return debugger.isolate.pause();
- } else {
- return new Future.value(null);
- }
- }
-
- Future doRefreshStack() {
- if (debugger != null) {
- return debugger.refreshStack();
- } else {
- return new Future.value(null);
- }
- }
-
DebuggerStackElement.created() : super.created();
}
-@CustomTag('debugger-frame')
-class DebuggerFrameElement extends ObservatoryElement {
- @published Frame frame;
- @published Element scroller;
+class DebuggerFrameElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerFrameElement>('debugger-frame');
+
+ RenderingScheduler<DebuggerMessageElement> _r;
+
+ Stream<RenderedEvent<DebuggerMessageElement>> get onRendered => _r.onRendered;
+
+ Element _scroller;
+ DivElement _varsDiv;
+ M.Isolate _isolate;
+ S.Frame _frame;
+ S.Frame get frame => _frame;
+ M.InstanceRepository _instances;
+ M.ScriptRepository _scripts;
+ M.EventRepository _events;
// Is this the current frame?
bool _current = false;
@@ -2213,99 +2337,238 @@ class DebuggerFrameElement extends ObservatoryElement {
// Has this frame been pinned open?
bool _pinned = false;
+ bool _expanded = false;
+
void setCurrent(bool value) {
- busy = true;
- frame.function.load().then((func) {
+ _frame.function.load().then((func) {
_current = value;
- var frameOuter = $['frameOuter'];
if (_current) {
- frameOuter.classes.add('current');
_expand();
scrollIntoView();
} else {
- frameOuter.classes.remove('current');
if (_pinned) {
_expand();
} else {
_unexpand();
}
}
- busy = false;
});
}
- @observable String scriptHeight;
- @observable bool expanded = false;
- @observable bool busy = false;
+ factory DebuggerFrameElement(M.Isolate isolate,
+ S.Frame frame,
+ Element scroller,
+ M.InstanceRepository instances,
+ M.ScriptRepository scripts,
+ M.EventRepository events,
+ {RenderingQueue queue}) {
+ assert(isolate != null);
+ assert(frame != null);
+ assert(scroller != null);
+ assert(instances != null);
+ assert(scripts != null);
+ assert(events != null);
+ final DebuggerFrameElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._isolate = isolate;
+ e._frame = frame;
+ e._scroller = scroller;
+ e._instances = instances;
+ e._scripts = scripts;
+ e._events = events;
+ return e;
+ }
DebuggerFrameElement.created() : super.created();
+ void render() {
+ if (_pinned) {
+ classes.add('shadow');
+ } else {
+ classes.remove('shadow');
+ }
+ if (_current) {
+ classes.add('current');
+ } else {
+ classes.remove('current');
+ }
+ ButtonElement expandButton;
+ final content = <Element>[
+ expandButton = new ButtonElement()
+ ..children = _createHeader()
+ ..onClick.listen((e) async {
+ if (e.target is AnchorElement) {
+ return;
+ }
+ expandButton.disabled = true;
+ await _toggleExpand();
+ expandButton.disabled = false;
+ })
+ ];
+ if (_expanded) {
+ final homeMethod = _frame.function.homeMethod;
+ String homeMethodName;
+ if ((homeMethod.dartOwner is S.Class) && homeMethod.isStatic) {
+ homeMethodName = '<class>';
+ } else if (homeMethod.dartOwner is S.Library) {
+ homeMethodName = '<library>';
+ }
+ ButtonElement collapseButton;
+ content.addAll([
+ new DivElement()..classes = ['frameDetails']
+ ..children = [
+ new DivElement()..classes = ['flex-row-wrap']
+ ..children = [
+ new DivElement()..classes = ['flex-item-script']
+ ..children = _frame.function?.location == null ? const []
+ : [
+ new SourceInsetElement(_isolate,
+ _frame.function.location, _scripts, _instances,
+ _events, currentPos: _frame.location.tokenPos,
+ variables: _frame.variables, inDebuggerContext: true,
+ queue: _r.queue)
+ ],
+ new DivElement()..classes = ['flex-item-vars']
+ ..children = [
+ _varsDiv = new DivElement()
+ ..classes = ['memberList', 'frameVars']
+ ..children = ([
+ new DivElement()..classes = ['memberItem']
+ ..children = homeMethodName == null ? const []
+ : [
+ new DivElement()..classes = ['memberName']
+ ..text = homeMethodName,
+ new DivElement()..classes = ['memberName']
+ ..children = [
+ anyRef(_isolate, homeMethod.dartOwner,
+ _instances, queue: _r.queue)
+ ]
+ ]
+ ]..addAll(_frame.variables.map((v) =>
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = v.name,
+ new DivElement()..classes = ['memberName']
+ ..children = [
+ anyRef(_isolate, v['value'], _instances,
+ queue: _r.queue)
+ ]
+ ]
+ ).toList()))
+ ]
+ ],
+ new DivElement()..classes = ['frameContractor']
+ ..children = [
+ collapseButton = new ButtonElement()
+ ..onClick.listen((e) async {
+ collapseButton.disabled = true;
+ await _toggleExpand();
+ collapseButton.disabled = false;
+ })
+ ..children = [
+ iconExpandLess.clone(true)
+ ]
+ ]
+ ]
+ ]);
+ }
+ children = content;
+ }
+
+ List<Element> _createHeader() {
+ final content = [
+ new DivElement()..classes = ['frameSummaryText']
+ ..children = [
+ new DivElement()..classes = ['frameId']
+ ..text = 'Frame ${_frame.index}',
+ new SpanElement()
+ ..children = _frame.function == null ? const []
+ : [
+ new FunctionRefElement(_isolate, _frame.function,
+ queue: _r.queue)
+ ],
+ new SpanElement()..text = ' ( ',
+ new SpanElement()
+ ..children = _frame.function?.location == null ? const []
+ : [
+ new SourceLinkElement(_isolate, _frame.function.location,
+ _scripts,
+ queue: _r.queue)
+ ],
+ new SpanElement()..text = ' )'
+ ]
+ ];
+ if (!_expanded) {
+ content.add(new DivElement()..classes = ['frameExpander']
+ ..children = [
+ iconExpandMore.clone(true)
+ ]);
+ }
+ return [
+ new DivElement()..classes = ['frameSummary']
+ ..children = content
+ ];
+ }
+
String makeExpandKey(String key) {
- return '${frame.function.qualifiedName}/${key}';
+ return '${_frame.function.qualifiedName}/${key}';
}
- bool matchFrame(Frame newFrame) {
- return newFrame.function.id == frame.function.id;
+ bool matchFrame(S.Frame newFrame) {
+ return newFrame.function.id == _frame.function.id;
}
- void updateFrame(Frame newFrame) {
+ void updateFrame(S.Frame newFrame) {
assert(matchFrame(newFrame));
- frame = newFrame;
+ _frame = newFrame;
}
- Script get script => frame.location.script;
+ S.Script get script => _frame.location.script;
int _varsTop(varsDiv) {
- const minTop = 5;
+ const minTop = 0;
if (varsDiv == null) {
return minTop;
}
- // TODO (cbernaschina) check if this is needed.
- const navbarHeight = 40;
- const bottomPad = 6;
- var parent = varsDiv.parent.getBoundingClientRect();
- var varsHeight = varsDiv.clientHeight;
- var maxTop = parent.height - (varsHeight + bottomPad);
- var adjustedTop = navbarHeight - parent.top;
+ final paddingTop = document.body.contentEdge.top;
+ final parent = varsDiv.parent.getBoundingClientRect();
+ final varsHeight = varsDiv.clientHeight;
+ final maxTop = parent.height - varsHeight;
+ final adjustedTop = paddingTop - parent.top;
return (max(minTop, min(maxTop, adjustedTop)));
}
void _onScroll(event) {
- if (!expanded) {
+ if (!_expanded || _varsDiv == null) {
return;
}
- var varsDiv = shadowRoot.querySelector('#vars');
- if (varsDiv == null) {
- return;
- }
- var currentTop = varsDiv.style.top;
- var newTop = _varsTop(varsDiv);
+ var currentTop = _varsDiv.style.top;
+ var newTop = _varsTop(_varsDiv);
if (currentTop != newTop) {
- varsDiv.style.top = '${newTop}px';
+ _varsDiv.style.top = '${newTop}px';
}
}
void _expand() {
- var frameOuter = $['frameOuter'];
- expanded = true;
- frameOuter.classes.add('shadow');
+ _expanded = true;
_subscribeToScroll();
+ _r.dirty();
}
void _unexpand() {
- var frameOuter = $['frameOuter'];
- expanded = false;
+ _expanded = false;
_unsubscribeToScroll();
- frameOuter.classes.remove('shadow');
+ _r.dirty();
}
StreamSubscription _scrollSubscription;
StreamSubscription _resizeSubscription;
void _subscribeToScroll() {
- if (scroller != null) {
+ if (_scroller != null) {
if (_scrollSubscription == null) {
- _scrollSubscription = scroller.onScroll.listen(_onScroll);
+ _scrollSubscription = _scroller.onScroll.listen(_onScroll);
}
if (_resizeSubscription == null) {
_resizeSubscription = window.onResize.listen(_onScroll);
@@ -2327,56 +2590,42 @@ class DebuggerFrameElement extends ObservatoryElement {
@override
void attached() {
super.attached();
- int windowHeight = window.innerHeight;
- scriptHeight = '${windowHeight ~/ 1.6}px';
- if (expanded) {
+ _r.enable();
+ if (_expanded) {
_subscribeToScroll();
}
}
void detached() {
- _unsubscribeToScroll();
+ _r.disable(notify: true);
super.detached();
+ _unsubscribeToScroll();
}
- void toggleExpand(var a, var b, var c) {
- if (busy) {
- return;
- }
- busy = true;
- frame.function.load().then((func) {
- _pinned = !_pinned;
- if (_pinned) {
- _expand();
- } else {
- _unexpand();
- }
- busy = false;
- });
- }
-
- @observable
- get properLocals {
- var locals = new List();
- var homeMethod = frame.function.homeMethod;
- if (homeMethod.dartOwner is Class && homeMethod.isStatic) {
- locals.add(
- {'name' : '<class>',
- 'value' : homeMethod.dartOwner});
- } else if (homeMethod.dartOwner is Library) {
- locals.add(
- {'name' : '<library>',
- 'value' : homeMethod.dartOwner});
+ Future _toggleExpand() async {
+ await _frame.function.load();
+ _pinned = !_pinned;
+ if (_pinned) {
+ _expand();
+ } else {
+ _unexpand();
}
- locals.addAll(frame.variables);
- return locals;
}
}
-@CustomTag('debugger-message')
-class DebuggerMessageElement extends ObservatoryElement {
- @published ServiceMessage message;
- @observable ServiceObject preview;
+class DebuggerMessageElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerMessageElement>('debugger-message');
+
+ RenderingScheduler<DebuggerMessageElement> _r;
+
+ Stream<RenderedEvent<DebuggerMessageElement>> get onRendered => _r.onRendered;
+
+ S.Isolate _isolate;
+ S.ServiceMessage _message;
+ S.ServiceObject _preview;
+ M.InstanceRepository _instances;
+ M.ScriptRepository _scripts;
+ M.EventRepository _events;
// Is this the current message?
bool _current = false;
@@ -2384,90 +2633,207 @@ class DebuggerMessageElement extends ObservatoryElement {
// Has this message been pinned open?
bool _pinned = false;
+ bool _expanded = false;
+
+ factory DebuggerMessageElement(S.Isolate isolate,
+ S.ServiceMessage message,
+ M.InstanceRepository instances,
+ M.ScriptRepository scripts,
+ M.EventRepository events,
+ {RenderingQueue queue}) {
+ assert(isolate != null);
+ assert(message != null);
+ assert(instances != null);
+ assert(instances != null);
+ assert(events != null);
+ final DebuggerMessageElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._isolate = isolate;
+ e._message = message;
+ e._instances = instances;
+ e._scripts = scripts;
+ e._events = events;
+ return e;
+ }
+
+ DebuggerMessageElement.created() : super.created();
+
+ void render() {
+ if (_pinned) {
+ classes.add('shadow');
+ } else {
+ classes.remove('shadow');
+ }
+ if (_current) {
+ classes.add('current');
+ } else {
+ classes.remove('current');
+ }
+ ButtonElement expandButton;
+ final content = <Element>[
+ expandButton = new ButtonElement()
+ ..children = _createHeader()
+ ..onClick.listen((e) async {
+ if (e.target is AnchorElement) {
+ return;
+ }
+ expandButton.disabled = true;
+ await _toggleExpand();
+ expandButton.disabled = false;
+ })
+ ];
+ if (_expanded) {
+ ButtonElement collapseButton;
+ ButtonElement previewButton;
+ content.addAll([
+ new DivElement()..classes = ['messageDetails']
+ ..children = [
+ new DivElement()..classes = ['flex-row-wrap']
+ ..children = [
+ new DivElement()..classes = ['flex-item-script']
+ ..children = _message.handler == null ? const []
+ : [
+ new SourceInsetElement(_isolate,
+ _message.handler.location,
+ _scripts,
+ _instances,
+ _events,
+ inDebuggerContext: true,
+ queue: _r.queue)
+ ],
+ new DivElement()..classes = ['flex-item-vars']
+ ..children = [
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName'],
+ new DivElement()..classes = ['memberValue']
+ ..children = ([
+ previewButton = new ButtonElement()
+ ..text = 'preview'
+ ..onClick.listen((_) {
+ previewButton.disabled = true;
+
+ })
+ ]..addAll(
+ _preview == null ? const []
+ : [
+ anyRef(_isolate, _preview, _instances,
+ queue: _r.queue)
+ ]
+ ))
+ ]
+ ]
+ ],
+ new DivElement()..classes = ['messageContractor']
+ ..children = [
+ collapseButton = new ButtonElement()
+ ..onClick.listen((e) async {
+ collapseButton.disabled = true;
+ await _toggleExpand();
+ collapseButton.disabled = false;
+ })
+ ..children = [
+ iconExpandLess.clone(true)
+ ]
+ ]
+ ]
+ ]);
+ }
+ children = content;
+ }
+
+ void updateMessage(S.ServiceMessage message) {
+ assert(_message != null);
+ _message = message;
+ _r.dirty();
+ }
+
+ List<Element> _createHeader() {
+ final content = [
+ new DivElement()..classes = ['messageSummaryText']
+ ..children = [
+ new DivElement()..classes = ['messageId']
+ ..text = 'message ${_message.index}',
+ new SpanElement()
+ ..children = _message.handler == null ? const []
+ : [
+ new FunctionRefElement(_isolate, _message.handler,
+ queue: _r.queue)
+ ],
+ new SpanElement()..text = ' ( ',
+ new SpanElement()
+ ..children = _message.location == null ? const []
+ : [
+ new SourceLinkElement(_isolate, _message.location, _scripts,
+ queue: _r.queue)
+ ],
+ new SpanElement()..text = ' )'
+ ]
+ ];
+ if (!_expanded) {
+ content.add(new DivElement()..classes = ['messageExpander']
+ ..children = [
+ iconExpandMore.clone(true)
+ ]);
+ }
+ return [
+ new DivElement()..classes = ['messageSummary']
+ ..children = content
+ ];
+ }
+
void setCurrent(bool value) {
_current = value;
- var messageOuter = $['messageOuter'];
if (_current) {
- messageOuter.classes.add('current');
- expanded = true;
- messageOuter.classes.add('shadow');
+ _expanded = true;
scrollIntoView();
+ _r.dirty();
} else {
- messageOuter.classes.remove('current');
- if (_pinned) {
- expanded = true;
- messageOuter.classes.add('shadow');
- } else {
- expanded = false;
- messageOuter.classes.remove('shadow');
- }
- }
- }
-
- @observable String scriptHeight;
- @observable bool expanded = false;
- @observable bool busy = false;
-
- DebuggerMessageElement.created() : super.created();
-
- void updateMessage(ServiceMessage newMessage) {
- bool messageChanged =
- (message.messageObjectId != newMessage.messageObjectId);
- message = newMessage;
- if (messageChanged) {
- // Message object id has changed: clear preview and collapse.
- preview = null;
- if (expanded) {
- toggleExpand(null, null, null);
- }
+ _expanded = _pinned;
}
}
@override
void attached() {
super.attached();
- int windowHeight = window.innerHeight;
- scriptHeight = '${windowHeight ~/ 1.6}px';
+ _r.enable();
}
- void toggleExpand(var a, var b, var c) {
- if (busy) {
- return;
+ @override
+ void detached() {
+ super.detached();
+ _r.disable(notify: true);
+ children = [];
+ }
+
+ Future _toggleExpand() async {
+ var function = _message.handler;
+ if (function != null) {
+ await function.load();
}
- busy = true;
- var function = message.handler;
- var loadedFunction;
- if (function == null) {
- // Complete immediately.
- loadedFunction = new Future.value(null);
- } else {
- loadedFunction = function.load();
- }
- loadedFunction.then((_) {
- _pinned = !_pinned;
- var messageOuter = $['messageOuter'];
- if (_pinned) {
- expanded = true;
- messageOuter.classes.add('shadow');
- } else {
- expanded = false;
- messageOuter.classes.remove('shadow');
- }
- busy = false;
- });
+ _pinned = _pinned;
+ _expanded = true;
+ _r.dirty();
}
- Future<ServiceObject> previewMessage(_) {
- return message.isolate.getObject(message.messageObjectId).then((result) {
- preview = result;
+ Future<S.ServiceObject> previewMessage(_) {
+ return _message.isolate.getObject(_message.messageObjectId).then((result) {
+ _preview = result;
return result;
});
}
}
-@CustomTag('debugger-console')
-class DebuggerConsoleElement extends ObservatoryElement {
- @published Isolate isolate;
+class DebuggerConsoleElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerConsoleElement>('debugger-console');
+
+ factory DebuggerConsoleElement() {
+ final DebuggerConsoleElement e = document.createElement(tag.name);
+ e.children = [
+ new BRElement()
+ ];
+ return e;
+ }
DebuggerConsoleElement.created() : super.created();
@@ -2495,9 +2861,8 @@ class DebuggerConsoleElement extends ObservatoryElement {
}
void _append(HtmlElement span) {
- var consoleTextElement = $['consoleText'];
bool autoScroll = _isScrolledToBottom(parent);
- consoleTextElement.children.add(span);
+ children.add(span);
if (autoScroll) {
_scrollToBottom(parent);
}
@@ -2534,24 +2899,23 @@ class DebuggerConsoleElement extends ObservatoryElement {
}
void printStdio(List<String> lines) {
- var consoleTextElement = $['consoleText'];
bool autoScroll = _isScrolledToBottom(parent);
for (var line in lines) {
var span = new SpanElement();
span.classes.add('green');
span.appendText(line);
span.appendText('\n');
- consoleTextElement.children.add(span);
+ children.add(span);
}
if (autoScroll) {
_scrollToBottom(parent);
}
}
- void printRef(Instance ref, { bool newline:true }) {
- var refElement = new Element.tag('instance-ref');
- refElement.ref = ref;
- _append(refElement);
+ void printRef(S.Isolate isolate, S.Instance ref,
+ M.InstanceRepository instances,{ bool newline:true }) {
+ _append(new InstanceRefElement(isolate, ref, instances,
+ queue: app.queue));
if (newline) {
this.newline();
}
@@ -2562,20 +2926,168 @@ class DebuggerConsoleElement extends ObservatoryElement {
}
void clear() {
- var consoleTextElement = $['consoleText'];
- consoleTextElement.children.clear();
+ children.clear();
}
+
+ ObservatoryApplication get app => ObservatoryApplication.app;
}
-@CustomTag('debugger-input')
-class DebuggerInputElement extends ObservatoryElement {
- @published Isolate isolate;
- @published String text = '';
- @observable ObservatoryDebugger debugger;
- @observable bool busy = false;
- @observable String modalPrompt = null;
+class DebuggerInputElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<DebuggerInputElement>('debugger-input');
+
+ S.Isolate _isolate;
+ ObservatoryDebugger _debugger;
+ bool _busy = false;
+ final _modalPromptDiv = new DivElement()
+ ..classes = ['modalPrompt', 'hidden'];
+ final _textBox = new TextInputElement()
+ ..classes = ['textBox']
+ ..autofocus = true;
+ String get modalPrompt => _modalPromptDiv.text;
+ set modalPrompt(String value) {
+ if (_modalPromptDiv.text == '') {
+ _modalPromptDiv.classes.remove('hidden');
+ }
+ _modalPromptDiv.text = value;
+ if (_modalPromptDiv.text == '') {
+ _modalPromptDiv.classes.add('hidden');
+ }
+ }
+ String get text => _textBox.value;
+ set text(String value) => _textBox.value = value;
var modalCallback = null;
+ factory DebuggerInputElement(S.Isolate isolate,
+ ObservatoryDebugger debugger) {
+ final DebuggerInputElement e = document.createElement(tag.name);
+ e.children = [
+ e._modalPromptDiv,
+ e._textBox
+ ];
+ e._textBox.select();
+ e._textBox.onKeyDown.listen(e._onKeyDown);
+ return e;
+ }
+
+ DebuggerInputElement.created() : super.created();
+
+ void _onKeyDown(KeyboardEvent e) {
+ if (_busy) {
+ e.preventDefault();
+ return;
+ }
+ _busy = true;
+ if (modalCallback != null) {
+ if (e.keyCode == KeyCode.ENTER) {
+ var response = text;
+ modalCallback(response).whenComplete(() {
+ text = '';
+ _busy = false;
+ });
+ } else {
+ _busy = false;
+ }
+ return;
+ }
+ switch (e.keyCode) {
+ case KeyCode.TAB:
+ e.preventDefault();
+ int cursorPos = _textBox.selectionStart;
+ _debugger.complete(text.substring(0, cursorPos)).then((completion) {
+ text = completion + text.substring(cursorPos);
+ // TODO(turnidge): Move the cursor to the end of the
+ // completion, rather than the end of the string.
+ }).whenComplete(() {
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.ENTER:
+ var command = text;
+ _debugger.run(command).whenComplete(() {
+ text = '';
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.UP:
+ e.preventDefault();
+ text = _debugger.historyPrev(text);
+ _busy = false;
+ break;
+
+ case KeyCode.DOWN:
+ e.preventDefault();
+ text = _debugger.historyNext(text);
+ _busy = false;
+ break;
+
+ case KeyCode.PAGE_UP:
+ e.preventDefault();
+ try {
+ _debugger.upFrame(1);
+ } on RangeError catch (_) {
+ // Ignore.
+ }
+ _busy = false;
+ break;
+
+ case KeyCode.PAGE_DOWN:
+ e.preventDefault();
+ try {
+ _debugger.downFrame(1);
+ } on RangeError catch (_) {
+ // Ignore.
+ }
+ _busy = false;
+ break;
+
+ case KeyCode.F7:
+ e.preventDefault();
+ _debugger.resume().whenComplete(() {
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.F8:
+ e.preventDefault();
+ _debugger.toggleBreakpoint().whenComplete(() {
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.F9:
+ e.preventDefault();
+ _debugger.smartNext().whenComplete(() {
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.F10:
+ e.preventDefault();
+ _debugger.step().whenComplete(() {
+ _busy = false;
+ });
+ break;
+
+ case KeyCode.SEMICOLON:
+ if (e.ctrlKey) {
+ e.preventDefault();
+ _debugger.console.printRed('^;');
+ _debugger.pause().whenComplete(() {
+ _busy = false;
+ });
+ } else {
+ _busy = false;
+ }
+ break;
+
+ default:
+ _busy = false;
+ break;
+ }
+ }
+
void enterMode(String prompt, callback) {
assert(modalPrompt == null);
modalPrompt = prompt;
@@ -2588,132 +3100,81 @@ class DebuggerInputElement extends ObservatoryElement {
modalCallback = null;
}
- @override
- void ready() {
- super.ready();
- var textBox = $['textBox'];
- textBox.select();
- textBox.onKeyDown.listen((KeyboardEvent e) {
- if (busy) {
- e.preventDefault();
- return;
- }
- busy = true;
- if (modalCallback != null) {
- if (e.keyCode == KeyCode.ENTER) {
- var response = text;
- modalCallback(response).whenComplete(() {
- text = '';
- busy = false;
- });
- } else {
- busy = false;
- }
- return;
- }
- switch (e.keyCode) {
- case KeyCode.TAB:
- e.preventDefault();
- int cursorPos = textBox.selectionStart;
- debugger.complete(text.substring(0, cursorPos)).then((completion) {
- text = completion + text.substring(cursorPos);
- // TODO(turnidge): Move the cursor to the end of the
- // completion, rather than the end of the string.
- }).whenComplete(() {
- busy = false;
- });
- break;
-
- case KeyCode.ENTER:
- var command = text;
- debugger.run(command).whenComplete(() {
- text = '';
- busy = false;
- });
- break;
-
- case KeyCode.UP:
- e.preventDefault();
- text = debugger.historyPrev(text);
- busy = false;
- break;
-
- case KeyCode.DOWN:
- e.preventDefault();
- text = debugger.historyNext(text);
- busy = false;
- break;
-
- case KeyCode.PAGE_UP:
- e.preventDefault();
- try {
- debugger.upFrame(1);
- } on RangeError catch (_) {
- // Ignore.
- }
- busy = false;
- break;
-
- case KeyCode.PAGE_DOWN:
- e.preventDefault();
- try {
- debugger.downFrame(1);
- } on RangeError catch (_) {
- // Ignore.
- }
- busy = false;
- break;
-
- case KeyCode.F7:
- e.preventDefault();
- debugger.resume().whenComplete(() {
- busy = false;
- });
- break;
-
- case KeyCode.F8:
- e.preventDefault();
- debugger.toggleBreakpoint().whenComplete(() {
- busy = false;
- });
- break;
-
- case KeyCode.F9:
- e.preventDefault();
- debugger.smartNext().whenComplete(() {
- busy = false;
- });
- break;
-
- case KeyCode.F10:
- e.preventDefault();
- debugger.step().whenComplete(() {
- busy = false;
- });
- break;
-
- case KeyCode.SEMICOLON:
- if (e.ctrlKey) {
- e.preventDefault();
- debugger.console.printRed('^;');
- debugger.pause().whenComplete(() {
- busy = false;
- });
- } else {
- busy = false;
- }
- break;
-
- default:
- busy = false;
- break;
- }
- });
- }
-
void focus() {
- $['textBox'].focus();
+ _textBox.focus();
}
-
- DebuggerInputElement.created() : super.created();
}
+
+final SvgSvgElement iconExpandLess = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PolygonElement()
+ ..setAttribute('points', '12,8 6,14 7.4,15.4 12,10.8 16.6,15.4 18,14 ')
+ ];
+
+final SvgSvgElement iconExpandMore = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PolygonElement()
+ ..setAttribute('points', '16.6,8.6 12,13.2 7.4,8.6 6,10 12,16 18,10 ')
+ ];
+
+final SvgSvgElement iconChevronRight = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z')
+ ];
+
+final SvgSvgElement iconChevronLeft = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z')
+ ];
+
+final SvgSvgElement iconHorizontalThreeDot = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+ '2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+ '2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+ '2-2-.9-2-2-2z')
+ ];
+
+final SvgSvgElement iconVerticalThreeDot = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 '
+ '2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+ '2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 '
+ '2-.9 2-2-.9-2-2-2z')
+ ];
+
+final SvgSvgElement iconInfo = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 '
+ '10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z')
+ ];
+
+final SvgSvgElement iconInfoOutline = new SvgSvgElement()
+ ..setAttribute('width', '24')
+ ..setAttribute('height', '24')
+ ..children = [
+ new PathElement()
+ ..setAttribute('d', 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
+ '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
+ '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
+ '9h2V7h-2v2z')
+ ];
« no previous file with comments | « runtime/observatory/lib/src/elements/css/shared.css ('k') | runtime/observatory/lib/src/elements/debugger.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698