blob: 5e48c6f65ed1ee2a070f33b4eb82d09c576d0eca [file] [log] [blame]
// Copyright 2015 Google. 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:async';
import 'dart:collection';
import '../webkit_inspection_protocol.dart';
class WipDebugger extends WipDomain {
final _scripts = <String, WipScript>{};
WipDebugger(WipConnection connection) : super(connection) {
onScriptParsed.listen((event) {
_scripts[event.script.scriptId] = event.script;
});
onGlobalObjectCleared.listen((_) {
_scripts.clear();
});
}
Future enable() => sendCommand('Debugger.enable');
Future disable() => sendCommand('Debugger.disable');
Future<String> getScriptSource(String scriptId) async =>
(await sendCommand('Debugger.getScriptSource',
params: {'scriptId': scriptId}))
.result['scriptSource'] as String;
Future pause() => sendCommand('Debugger.pause');
Future resume() => sendCommand('Debugger.resume');
Future stepInto() => sendCommand('Debugger.stepInto');
Future stepOut() => sendCommand('Debugger.stepOut');
Future stepOver() => sendCommand('Debugger.stepOver');
Future setPauseOnExceptions(PauseState state) =>
sendCommand('Debugger.setPauseOnExceptions',
params: {'state': _pauseStateToString(state)});
Stream<DebuggerPausedEvent> get onPaused => eventStream(
'Debugger.paused', (WipEvent event) => new DebuggerPausedEvent(event));
Stream<GlobalObjectClearedEvent> get onGlobalObjectCleared => eventStream(
'Debugger.globalObjectCleared',
(WipEvent event) => new GlobalObjectClearedEvent(event));
Stream<DebuggerResumedEvent> get onResumed => eventStream(
'Debugger.resumed', (WipEvent event) => new DebuggerResumedEvent(event));
Stream<ScriptParsedEvent> get onScriptParsed => eventStream(
'Debugger.scriptParsed',
(WipEvent event) => new ScriptParsedEvent(event));
Map<String, WipScript> get scripts => new UnmodifiableMapView(_scripts);
}
String _pauseStateToString(PauseState state) {
switch (state) {
case PauseState.all:
return 'all';
case PauseState.none:
return 'none';
case PauseState.uncaught:
return 'uncaught';
default:
throw new ArgumentError('unknown state: $state');
}
}
enum PauseState { all, none, uncaught }
class ScriptParsedEvent extends WrappedWipEvent {
final WipScript script;
ScriptParsedEvent(WipEvent event)
: this.script = new WipScript(event.params),
super(event);
}
class GlobalObjectClearedEvent extends WrappedWipEvent {
GlobalObjectClearedEvent(WipEvent event) : super(event);
}
class DebuggerResumedEvent extends WrappedWipEvent {
DebuggerResumedEvent(WipEvent event) : super(event);
}
class DebuggerPausedEvent extends WrappedWipEvent {
DebuggerPausedEvent(WipEvent event) : super(event);
String get reason => params['reason'] as String;
Object get data => params['data'];
Iterable<WipCallFrame> getCallFrames() => (params['callFrames'] as List)
.map((frame) => new WipCallFrame(frame as Map<String, dynamic>));
String toString() => 'paused: ${reason}';
}
class WipCallFrame {
final Map<String, dynamic> _map;
WipCallFrame(this._map);
String get callFrameId => _map['callFrameId'] as String;
String get functionName => _map['functionName'] as String;
WipLocation get location =>
new WipLocation(_map['location'] as Map<String, dynamic>);
WipRemoteObject get thisObject =>
new WipRemoteObject(_map['this'] as Map<String, dynamic>);
Iterable<WipScope> getScopeChain() => (_map['scopeChain'] as List)
.map((scope) => new WipScope(scope as Map<String, dynamic>));
String toString() => '[${functionName}]';
}
class WipLocation {
final Map<String, dynamic> _map;
WipLocation(this._map);
int get columnNumber => _map['columnNumber'] as int;
int get lineNumber => _map['lineNumber'] as int;
String get scriptId => _map['scriptId'] as String;
String toString() => '[${scriptId}:${lineNumber}:${columnNumber}]';
}
class WipRemoteObject {
final Map<String, dynamic> _map;
WipRemoteObject(this._map);
String get className => _map['className'] as String;
String get description => _map['description'] as String;
String get objectId => _map['objectId'] as String;
String get subtype => _map['subtype'] as String;
String get type => _map['type'] as String;
Object get value => _map['value'];
}
class WipScript {
final Map<String, dynamic> _map;
WipScript(this._map);
String get scriptId => _map['scriptId'] as String;
String get url => _map['url'] as String;
int get startLine => _map['startLine'] as int;
int get startColumn => _map['startColumn'] as int;
int get endLine => _map['endLine'] as int;
int get endColumn => _map['endColumn'] as int;
bool get isContentScript => _map['isContentScript'] as bool;
String get sourceMapURL => _map['sourceMapURL'] as String;
String toString() => '[script ${scriptId}: ${url}]';
}
class WipScope {
final Map<String, dynamic> _map;
WipScope(this._map);
// "catch", "closure", "global", "local", "with"
String get scope => _map['scope'] as String;
/**
* Object representing the scope. For global and with scopes it represents the
* actual object; for the rest of the scopes, it is artificial transient
* object enumerating scope variables as its properties.
*/
WipRemoteObject get object =>
new WipRemoteObject(_map['object'] as Map<String, dynamic>);
}