expose more methods; change API; rev version (#58)
expose more methods; change API; rev version
diff --git a/changelog.md b/changelog.md
index ec149a6..8ed2a8c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,13 @@
# webkit_inspection_protocol.dart
+## 0.7.0
+- Normalized all objects to expose a `json` field for raw access to the protocol information.
+- Exposed Runtime.getProperties, Runtime.getHeapUsage, and Runtime.getIsolateId
+- Exposed `DebuggerPausedEvent.hitBreakpoints` and `DebuggerPausedEvent.asyncStackTrace`
+- Exposed `WipCallFrame.returnValue`
+- Removed `WrappedWipEvent` (in favor of just using `WipEvent`)
+- Removed `WipRemoteObject` (in favor of just using `RemoteObject`)
+
## 0.6.0
- Add `onSend` and `onReceive` in `WipConnection`
- Expose `onExecutionContextCreated`, `onExecutionContextDestroyed`,
diff --git a/lib/src/console.dart b/lib/src/console.dart
index 72d9e27..e1500d7 100644
--- a/lib/src/console.dart
+++ b/lib/src/console.dart
@@ -17,15 +17,15 @@
Stream<ConsoleMessageEvent> get onMessage => eventStream(
'Console.messageAdded',
- (WipEvent event) => new ConsoleMessageEvent(event));
+ (WipEvent event) => new ConsoleMessageEvent(event.json));
Stream<ConsoleClearedEvent> get onCleared => eventStream(
'Console.messagesCleared',
- (WipEvent event) => new ConsoleClearedEvent(event));
+ (WipEvent event) => new ConsoleClearedEvent(event.json));
}
-class ConsoleMessageEvent extends WrappedWipEvent {
- ConsoleMessageEvent(WipEvent event) : super(event);
+class ConsoleMessageEvent extends WipEvent {
+ ConsoleMessageEvent(Map<String, dynamic> json) : super(json);
Map get _message => params['message'] as Map;
@@ -47,22 +47,22 @@
String toString() => text;
}
-class ConsoleClearedEvent extends WrappedWipEvent {
- ConsoleClearedEvent(WipEvent event) : super(event);
+class ConsoleClearedEvent extends WipEvent {
+ ConsoleClearedEvent(Map<String, dynamic> json) : super(json);
}
class WipConsoleCallFrame {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- WipConsoleCallFrame.fromMap(this._map);
+ WipConsoleCallFrame.fromMap(this.json);
- int get columnNumber => _map['columnNumber'] as int;
+ int get columnNumber => json['columnNumber'] as int;
- String get functionName => _map['functionName'] as String;
+ String get functionName => json['functionName'] as String;
- int get lineNumber => _map['lineNumber'] as int;
+ int get lineNumber => json['lineNumber'] as int;
- String get scriptId => _map['scriptId'] as String;
+ String get scriptId => json['scriptId'] as String;
- String get url => _map['url'] as String;
+ String get url => json['url'] as String;
}
diff --git a/lib/src/debugger.dart b/lib/src/debugger.dart
index 1c928cd..ae7cb62 100644
--- a/lib/src/debugger.dart
+++ b/lib/src/debugger.dart
@@ -22,10 +22,11 @@
Future<WipResponse> disable() => sendCommand('Debugger.disable');
- Future<String> getScriptSource(String scriptId) async =>
- (await sendCommand('Debugger.getScriptSource',
- params: {'scriptId': scriptId}))
- .result['scriptSource'] as String;
+ Future<String> getScriptSource(String scriptId) async {
+ return (await sendCommand('Debugger.getScriptSource',
+ params: {'scriptId': scriptId}))
+ .result['scriptSource'] as String;
+ }
Future<WipResponse> pause() => sendCommand('Debugger.pause');
@@ -142,19 +143,19 @@
}
}
- Stream<DebuggerPausedEvent> get onPaused => eventStream(
- 'Debugger.paused', (WipEvent event) => new DebuggerPausedEvent(event));
+ Stream<DebuggerPausedEvent> get onPaused => eventStream('Debugger.paused',
+ (WipEvent event) => new DebuggerPausedEvent(event.json));
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<DebuggerResumedEvent> get onResumed => eventStream('Debugger.resumed',
+ (WipEvent event) => new DebuggerResumedEvent(event.json));
Stream<ScriptParsedEvent> get onScriptParsed => eventStream(
'Debugger.scriptParsed',
- (WipEvent event) => new ScriptParsedEvent(event));
+ (WipEvent event) => new ScriptParsedEvent(event.json));
Map<String, WipScript> get scripts => new UnmodifiableMapView(_scripts);
}
@@ -174,158 +175,177 @@
enum PauseState { all, none, uncaught }
-class ScriptParsedEvent extends WrappedWipEvent {
- final WipScript script;
+class ScriptParsedEvent extends WipEvent {
+ ScriptParsedEvent(Map<String, dynamic> json) : super(json);
- ScriptParsedEvent(WipEvent event)
- : this.script = new WipScript(event.params),
- super(event);
+ WipScript get script => new WipScript(params);
String toString() => script.toString();
}
-class GlobalObjectClearedEvent extends WrappedWipEvent {
- GlobalObjectClearedEvent(WipEvent event) : super(event);
+class GlobalObjectClearedEvent extends WipEvent {
+ GlobalObjectClearedEvent(json) : super(json);
}
-class DebuggerResumedEvent extends WrappedWipEvent {
- DebuggerResumedEvent(WipEvent event) : super(event);
+class DebuggerResumedEvent extends WipEvent {
+ DebuggerResumedEvent(Map<String, dynamic> json) : super(json);
}
-class DebuggerPausedEvent extends WrappedWipEvent {
- DebuggerPausedEvent(WipEvent event) : super(event);
+/// Fired when the virtual machine stopped on breakpoint or exception or any
+/// other stop criteria.
+class DebuggerPausedEvent extends WipEvent {
+ DebuggerPausedEvent(Map<String, dynamic> json) : super(json);
+ /// Call stack the virtual machine stopped on.
+ List<WipCallFrame> getCallFrames() => (params['callFrames'] as List)
+ .map((frame) => new WipCallFrame(frame as Map<String, dynamic>))
+ .toList();
+
+ /// Pause reason.
+ ///
+ /// Allowed Values: ambiguous, assert, debugCommand, DOM, EventListener,
+ /// exception, instrumentation, OOM, other, promiseRejection, XHR.
String get reason => params['reason'] as String;
+ /// Object containing break-specific auxiliary properties.
Object get data => params['data'];
- Iterable<WipCallFrame> getCallFrames() => (params['callFrames'] as List)
- .map((frame) => new WipCallFrame(frame as Map<String, dynamic>));
+ /// Hit breakpoints IDs (optional).
+ List<String> get hitBreakpoints {
+ if (params['hitBreakpoints'] == null) return null;
+ return (params['hitBreakpoints'] as List).cast<String>();
+ }
+
+ /// Async stack trace, if any.
+ StackTrace get asyncStackTrace => params['asyncStackTrace'] == null
+ ? null
+ : StackTrace(params['asyncStackTrace']);
String toString() => 'paused: ${reason}';
}
class WipCallFrame {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- WipCallFrame(this._map);
+ WipCallFrame(this.json);
- String get callFrameId => _map['callFrameId'] as String;
+ /// Call frame identifier.
+ ///
+ /// This identifier is only valid while the virtual machine is paused.
+ String get callFrameId => json['callFrameId'] as String;
- String get functionName => _map['functionName'] as String;
+ /// Name of the JavaScript function called on this call frame.
+ String get functionName => json['functionName'] as String;
+ /// Location in the source code.
WipLocation get location =>
- new WipLocation(_map['location'] as Map<String, dynamic>);
+ new WipLocation(json['location'] as Map<String, dynamic>);
- WipRemoteObject get thisObject =>
- new WipRemoteObject(_map['this'] as Map<String, dynamic>);
+ /// JavaScript script name or url.
+ String get url => json['url'] as String;
- Iterable<WipScope> getScopeChain() => (_map['scopeChain'] as List)
+ /// Scope chain for this call frame.
+ Iterable<WipScope> getScopeChain() => (json['scopeChain'] as List)
.map((scope) => new WipScope(scope as Map<String, dynamic>));
+ /// `this` object for this call frame.
+ RemoteObject get thisObject =>
+ new RemoteObject(json['this'] as Map<String, dynamic>);
+
+ /// The value being returned, if the function is at return point.
+ ///
+ /// (optional)
+ RemoteObject get returnValue {
+ return json.containsKey('returnValue')
+ ? new RemoteObject(json['returnValue'] as Map<String, dynamic>)
+ : null;
+ }
+
String toString() => '[${functionName}]';
}
class WipLocation {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- WipLocation(this._map);
+ WipLocation(this.json);
WipLocation.fromValues(String scriptId, int lineNumber, {int columnNumber})
- : _map = {} {
- _map['scriptId'] = scriptId;
- _map['lineNumber'] = lineNumber;
+ : json = {} {
+ json['scriptId'] = scriptId;
+ json['lineNumber'] = lineNumber;
if (columnNumber != null) {
- _map['columnNumber'] = columnNumber;
+ json['columnNumber'] = columnNumber;
}
}
- String get scriptId => _map['scriptId'];
+ String get scriptId => json['scriptId'];
- int get lineNumber => _map['lineNumber'];
+ int get lineNumber => json['lineNumber'];
- int get columnNumber => _map['columnNumber'];
+ int get columnNumber => json['columnNumber'];
Map<String, dynamic> toJsonMap() {
- return _map;
+ return json;
}
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;
+ final Map<String, dynamic> json;
- WipScript(this._map);
+ WipScript(this.json);
- String get scriptId => _map['scriptId'] as String;
+ String get scriptId => json['scriptId'] as String;
- String get url => _map['url'] as String;
+ String get url => json['url'] as String;
- int get startLine => _map['startLine'] as int;
+ int get startLine => json['startLine'] as int;
- int get startColumn => _map['startColumn'] as int;
+ int get startColumn => json['startColumn'] as int;
- int get endLine => _map['endLine'] as int;
+ int get endLine => json['endLine'] as int;
- int get endColumn => _map['endColumn'] as int;
+ int get endColumn => json['endColumn'] as int;
- bool get isContentScript => _map['isContentScript'] as bool;
+ bool get isContentScript => json['isContentScript'] as bool;
- String get sourceMapURL => _map['sourceMapURL'] as String;
+ String get sourceMapURL => json['sourceMapURL'] as String;
String toString() => '[script ${scriptId}: ${url}]';
}
class WipScope {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- WipScope(this._map);
+ WipScope(this.json);
// "catch", "closure", "global", "local", "with"
- String get scope => _map['type'] as String;
+ String get scope => json['type'] as String;
/// Name of the scope, null if unnamed closure or global scope
- String get name => _map['name'] as String;
+ String get name => json['name'] 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>);
+ RemoteObject get object =>
+ new RemoteObject(json['object'] as Map<String, dynamic>);
}
class WipBreakLocation extends WipLocation {
- WipBreakLocation(Map<String, dynamic> map) : super(map);
+ WipBreakLocation(Map<String, dynamic> json) : super(json);
WipBreakLocation.fromValues(String scriptId, int lineNumber,
{int columnNumber, String type})
: super.fromValues(scriptId, lineNumber, columnNumber: columnNumber) {
if (type != null) {
- _map['type'] = type;
+ json['type'] = type;
}
}
/// Allowed Values: `debuggerStatement`, `call`, `return`.
- String get type => _map['type'];
+ String get type => json['type'];
}
/// The response from [WipDebugger.setBreakpoint].
diff --git a/lib/src/dom.dart b/lib/src/dom.dart
index e8929ff..d1fd1e5 100644
--- a/lib/src/dom.dart
+++ b/lib/src/dom.dart
@@ -118,14 +118,14 @@
return resp.result['nodeId'] as int;
}
- Future<WipRemoteObject> resolveNode(int nodeId, {String objectGroup}) async {
+ Future<RemoteObject> resolveNode(int nodeId, {String objectGroup}) async {
var params = <String, dynamic>{'nodeId': nodeId};
if (objectGroup != null) {
params['objectGroup'] = objectGroup;
}
var resp = await sendCommand('DOM.resolveNode', params: params);
- return new WipRemoteObject(resp.result['object'] as Map<String, dynamic>);
+ return new RemoteObject(resp.result['object'] as Map<String, dynamic>);
}
Future setAttributeValue(int nodeId, String name, String value) =>
@@ -156,64 +156,79 @@
Stream<AttributeModifiedEvent> get onAttributeModified => eventStream(
'DOM.attributeModified',
- (WipEvent event) => new AttributeModifiedEvent(event));
+ (WipEvent event) => new AttributeModifiedEvent(event.json));
+
Stream<AttributeRemovedEvent> get onAttributeRemoved => eventStream(
'DOM.attributeRemoved',
- (WipEvent event) => new AttributeRemovedEvent(event));
+ (WipEvent event) => new AttributeRemovedEvent(event.json));
+
Stream<CharacterDataModifiedEvent> get onCharacterDataModified => eventStream(
'DOM.characterDataModified',
- (WipEvent event) => new CharacterDataModifiedEvent(event));
+ (WipEvent event) => new CharacterDataModifiedEvent(event.json));
+
Stream<ChildNodeCountUpdatedEvent> get onChildNodeCountUpdated => eventStream(
'DOM.childNodeCountUpdated',
- (WipEvent event) => new ChildNodeCountUpdatedEvent(event));
+ (WipEvent event) => new ChildNodeCountUpdatedEvent(event.json));
+
Stream<ChildNodeInsertedEvent> get onChildNodeInserted => eventStream(
'DOM.childNodeInserted',
- (WipEvent event) => new ChildNodeInsertedEvent(event));
+ (WipEvent event) => new ChildNodeInsertedEvent(event.json));
+
Stream<ChildNodeRemovedEvent> get onChildNodeRemoved => eventStream(
'DOM.childNodeRemoved',
- (WipEvent event) => new ChildNodeRemovedEvent(event));
+ (WipEvent event) => new ChildNodeRemovedEvent(event.json));
+
Stream<DocumentUpdatedEvent> get onDocumentUpdated => eventStream(
'DOM.documentUpdated',
- (WipEvent event) => new DocumentUpdatedEvent(event));
+ (WipEvent event) => new DocumentUpdatedEvent(event.json));
+
Stream<SetChildNodesEvent> get onSetChildNodes => eventStream(
- 'DOM.setChildNodes', (WipEvent event) => new SetChildNodesEvent(event));
+ 'DOM.setChildNodes',
+ (WipEvent event) => new SetChildNodesEvent(event.json));
}
-class AttributeModifiedEvent extends WrappedWipEvent {
- AttributeModifiedEvent(WipEvent event) : super(event);
+class AttributeModifiedEvent extends WipEvent {
+ AttributeModifiedEvent(Map<String, dynamic> json) : super(json);
int get nodeId => params['nodeId'] as int;
+
String get name => params['name'] as String;
+
String get value => params['value'] as String;
}
-class AttributeRemovedEvent extends WrappedWipEvent {
- AttributeRemovedEvent(WipEvent event) : super(event);
+class AttributeRemovedEvent extends WipEvent {
+ AttributeRemovedEvent(Map<String, dynamic> json) : super(json);
int get nodeId => params['nodeId'] as int;
+
String get name => params['name'] as String;
}
-class CharacterDataModifiedEvent extends WrappedWipEvent {
- CharacterDataModifiedEvent(WipEvent event) : super(event);
+class CharacterDataModifiedEvent extends WipEvent {
+ CharacterDataModifiedEvent(Map<String, dynamic> json) : super(json);
int get nodeId => params['nodeId'] as int;
+
String get characterData => params['characterData'] as String;
}
-class ChildNodeCountUpdatedEvent extends WrappedWipEvent {
- ChildNodeCountUpdatedEvent(WipEvent event) : super(event);
+class ChildNodeCountUpdatedEvent extends WipEvent {
+ ChildNodeCountUpdatedEvent(Map<String, dynamic> json) : super(json);
int get nodeId => params['nodeId'] as int;
+
int get childNodeCount => params['childNodeCount'] as int;
}
-class ChildNodeInsertedEvent extends WrappedWipEvent {
- ChildNodeInsertedEvent(WipEvent event) : super(event);
+class ChildNodeInsertedEvent extends WipEvent {
+ ChildNodeInsertedEvent(Map<String, dynamic> json) : super(json);
int get parentNodeId => params['parentNodeId'] as int;
+
int get previousNodeId => params['previousNodeId'] as int;
Node _node;
+
Node get node {
if (_node == null) {
_node = new Node(params['node'] as Map<String, dynamic>);
@@ -222,21 +237,23 @@
}
}
-class ChildNodeRemovedEvent extends WrappedWipEvent {
- ChildNodeRemovedEvent(WipEvent event) : super(event);
+class ChildNodeRemovedEvent extends WipEvent {
+ ChildNodeRemovedEvent(Map<String, dynamic> json) : super(json);
int get parentNodeId => params['parentNodeId'] as int;
+
int get nodeId => params['nodeId'] as int;
}
-class DocumentUpdatedEvent extends WrappedWipEvent {
- DocumentUpdatedEvent(WipEvent event) : super(event);
+class DocumentUpdatedEvent extends WipEvent {
+ DocumentUpdatedEvent(Map<String, dynamic> json) : super(json);
}
-class SetChildNodesEvent extends WrappedWipEvent {
- SetChildNodesEvent(WipEvent event) : super(event);
+class SetChildNodesEvent extends WipEvent {
+ SetChildNodesEvent(Map<String, dynamic> json) : super(json);
int get nodeId => params['parentId'] as int;
+
Iterable<Node> get nodes sync* {
for (Map node in params['nodes']) {
yield new Node(node as Map<String, dynamic>);
@@ -255,6 +272,7 @@
Node(this._map);
Map<String, String> _attributes;
+
Map<String, String> get attributes {
if (_attributes == null && _map.containsKey('attributes')) {
_attributes = _attributeListToMap((_map['attributes'] as List).cast());
@@ -265,6 +283,7 @@
int get childNodeCount => _map['childNodeCount'] as int;
List<Node> _children;
+
List<Node> get children {
if (_children == null && _map.containsKey('children')) {
_children = new UnmodifiableListView((_map['children'] as List)
diff --git a/lib/src/log.dart b/lib/src/log.dart
index 772d453..6dc5b46 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -12,12 +12,12 @@
Future<WipResponse> disable() => sendCommand('Log.disable');
- Stream<LogEntry> get onEntryAdded =>
- eventStream('Log.entryAdded', (WipEvent event) => new LogEntry(event));
+ Stream<LogEntry> get onEntryAdded => eventStream(
+ 'Log.entryAdded', (WipEvent event) => new LogEntry(event.json));
}
-class LogEntry extends WrappedWipEvent {
- LogEntry(WipEvent event) : super(event);
+class LogEntry extends WipEvent {
+ LogEntry(Map<String, dynamic> json) : super(json);
Map<String, dynamic> get _entry => params['entry'] as Map<String, dynamic>;
diff --git a/lib/src/runtime.dart b/lib/src/runtime.dart
index bd6d647..b802289 100644
--- a/lib/src/runtime.dart
+++ b/lib/src/runtime.dart
@@ -64,8 +64,8 @@
/// object (int, String, double, bool).
Future<RemoteObject> callFunctionOn(
String functionDeclaration, {
- List<dynamic> arguments,
String objectId,
+ List<dynamic> arguments,
bool returnByValue,
int executionContextId,
}) async {
@@ -104,13 +104,57 @@
}
}
+ /// Returns the JavaScript heap usage. It is the total usage of the
+ /// corresponding isolate not scoped to a particular Runtime.
+ @experimental
+ Future<HeapUsage> getHeapUsage() async {
+ final WipResponse response = await sendCommand('Runtime.getHeapUsage');
+ return HeapUsage(response.result);
+ }
+
+ /// Returns the isolate id.
+ @experimental
+ Future<String> getIsolateId() async {
+ return (await sendCommand('Runtime.getIsolateId')).result['id'] as String;
+ }
+
+ /// Returns properties of a given object. Object group of the result is
+ /// inherited from the target object.
+ ///
+ /// objectId: Identifier of the object to return properties for.
+ ///
+ /// ownProperties: If true, returns properties belonging only to the element
+ /// itself, not to its prototype chain.
+ Future<List<PropertyDescriptor>> getProperties(
+ RemoteObject object, {
+ bool ownProperties,
+ }) async {
+ Map<String, dynamic> params = {
+ 'objectId': object.objectId,
+ };
+ if (ownProperties != null) {
+ params['ownProperties'] = ownProperties;
+ }
+
+ final WipResponse response =
+ await sendCommand('Runtime.getProperties', params: params);
+
+ if (response.result.containsKey('exceptionDetails')) {
+ throw new ExceptionDetails(
+ response.result['exceptionDetails'] as Map<String, dynamic>);
+ } else {
+ List locations = response.result['result'];
+ return List.from(locations.map((map) => PropertyDescriptor(map)));
+ }
+ }
+
Stream<ConsoleAPIEvent> get onConsoleAPICalled => eventStream(
'Runtime.consoleAPICalled',
- (WipEvent event) => new ConsoleAPIEvent(event));
+ (WipEvent event) => new ConsoleAPIEvent(event.json));
Stream<ExceptionThrownEvent> get onExceptionThrown => eventStream(
'Runtime.exceptionThrown',
- (WipEvent event) => new ExceptionThrownEvent(event));
+ (WipEvent event) => new ExceptionThrownEvent(event.json));
/// Issued when new execution context is created.
Stream<ExecutionContextDescription> get onExecutionContextCreated =>
@@ -129,44 +173,43 @@
'Runtime.executionContextsCleared', (WipEvent event) => event);
}
-class ConsoleAPIEvent extends WrappedWipEvent {
- ConsoleAPIEvent(WipEvent event) : super(event);
+// TODO: stackTrace, StackTrace, Stack trace captured when the call was made.
+class ConsoleAPIEvent extends WipEvent {
+ ConsoleAPIEvent(Map<String, dynamic> json) : super(json);
/// Type of the call. Allowed values: log, debug, info, error, warning, dir,
/// dirxml, table, trace, clear, startGroup, startGroupCollapsed, endGroup,
/// assert, profile, profileEnd.
String get type => params['type'] as String;
- // Call timestamp.
+ /// Call timestamp.
num get timestamp => params['timestamp'] as num;
/// Call arguments.
List<RemoteObject> get args => (params['args'] as List)
.map((m) => new RemoteObject(m as Map<String, dynamic>))
.toList();
-
-// TODO: stackTrace, StackTrace, Stack trace captured when the call was made.
}
/// Description of an isolated world.
class ExecutionContextDescription {
- final Map<String, dynamic> map;
+ final Map<String, dynamic> json;
- ExecutionContextDescription(this.map);
+ ExecutionContextDescription(this.json);
/// Unique id of the execution context. It can be used to specify in which
/// execution context script evaluation should be performed.
- int get id => map['id'] as int;
+ int get id => json['id'] as int;
/// Execution context origin.
- String get origin => map['origin'];
+ String get origin => json['origin'];
/// Human readable name describing given context.
- String get name => map['name'];
+ String get name => json['name'];
}
-class ExceptionThrownEvent extends WrappedWipEvent {
- ExceptionThrownEvent(WipEvent event) : super(event);
+class ExceptionThrownEvent extends WipEvent {
+ ExceptionThrownEvent(Map<String, dynamic> json) : super(json);
/// Timestamp of the exception.
int get timestamp => params['timestamp'] as int;
@@ -176,60 +219,59 @@
}
class ExceptionDetails implements Exception {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- ExceptionDetails(this._map);
-
- Map<String, dynamic> get json => _map;
+ ExceptionDetails(this.json);
/// Exception id.
- int get exceptionId => _map['exceptionId'] as int;
+ int get exceptionId => json['exceptionId'] as int;
/// Exception text, which should be used together with exception object when
/// available.
- String get text => _map['text'] as String;
+ String get text => json['text'] as String;
/// Line number of the exception location (0-based).
- int get lineNumber => _map['lineNumber'] as int;
+ int get lineNumber => json['lineNumber'] as int;
/// Column number of the exception location (0-based).
- int get columnNumber => _map['columnNumber'] as int;
+ int get columnNumber => json['columnNumber'] as int;
/// URL of the exception location, to be used when the script was not
/// reported.
@optional
- String get url => _map['url'] as String;
+ String get url => json['url'] as String;
/// Script ID of the exception location.
@optional
- String get scriptId => _map['scriptId'] as String;
+ String get scriptId => json['scriptId'] as String;
/// JavaScript stack trace if available.
@optional
- StackTrace get stackTrace => _map['stackTrace'] == null
+ StackTrace get stackTrace => json['stackTrace'] == null
? null
- : new StackTrace(_map['stackTrace'] as Map<String, dynamic>);
+ : new StackTrace(json['stackTrace'] as Map<String, dynamic>);
/// Exception object if available.
@optional
- RemoteObject get exception => _map['exception'] == null
+ RemoteObject get exception => json['exception'] == null
? null
- : new RemoteObject(_map['exception'] as Map<String, dynamic>);
+ : new RemoteObject(json['exception'] as Map<String, dynamic>);
String toString() => '$text, $url, $scriptId, $lineNumber, $exception';
}
+/// Call frames for assertions or error messages.
class StackTrace {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- StackTrace(this._map);
+ StackTrace(this.json);
/// String label of this stack trace. For async traces this may be a name of
/// the function that initiated the async call.
@optional
- String get description => _map['description'] as String;
+ String get description => json['description'] as String;
- List<CallFrame> get callFrames => (_map['callFrames'] as List)
+ List<CallFrame> get callFrames => (json['callFrames'] as List)
.map((m) => new CallFrame(m as Map<String, dynamic>))
.toList();
@@ -252,48 +294,113 @@
String toString() => callFrames.map((f) => ' $f').join('\n');
}
+/// Stack entry for runtime errors and assertions.
class CallFrame {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- CallFrame(this._map);
+ CallFrame(this.json);
/// JavaScript function name.
- String get functionName => _map['functionName'] as String;
+ String get functionName => json['functionName'] as String;
/// JavaScript script id.
- String get scriptId => _map['scriptId'] as String;
+ String get scriptId => json['scriptId'] as String;
/// JavaScript script name or url.
- String get url => _map['url'] as String;
+ String get url => json['url'] as String;
/// JavaScript script line number (0-based).
- int get lineNumber => _map['lineNumber'] as int;
+ int get lineNumber => json['lineNumber'] as int;
/// JavaScript script column number (0-based).
- int get columnNumber => _map['columnNumber'] as int;
+ int get columnNumber => json['columnNumber'] as int;
String toString() => '$functionName() ($url $lineNumber:$columnNumber)';
}
/// Mirror object referencing original JavaScript object.
class RemoteObject {
- final Map<String, dynamic> _map;
+ final Map<String, dynamic> json;
- RemoteObject(this._map);
+ RemoteObject(this.json);
- /// Object type.object, function, undefined, string, number, boolean, symbol,
- /// bigint.
- String get type => _map['type'] as String;
+ /// Object type.
+ ///
+ /// Allowed Values: object, function, undefined, string, number, boolean,
+ /// symbol, bigint, wasm.
+ String get type => json['type'] as String;
+
+ /// Object subtype hint. Specified for object or wasm type values only.
+ ///
+ /// Allowed Values: array, null, node, regexp, date, map, set, weakmap,
+ /// weakset, iterator, generator, error, proxy, promise, typedarray,
+ /// arraybuffer, dataview, i32, i64, f32, f64, v128, anyref.
+ String get subtype => json['subtype'] as String;
+
+ /// Object class (constructor) name.
+ ///
+ /// Specified for object type values only.
+ String get className => json['className'] as String;
/// Remote object value in case of primitive values or JSON values (if it was
/// requested). (optional)
- Object get value => _map['value'];
+ Object get value => json['value'];
/// String representation of the object. (optional)
- String get description => _map['description'] as String;
+ String get description => json['description'] as String;
/// Unique object identifier (for non-primitive values). (optional)
- String get objectId => _map['objectId'] as String;
+ String get objectId => json['objectId'] as String;
+ @override
String toString() => '$type $value';
}
+
+/// Returns the JavaScript heap usage. It is the total usage of the
+/// corresponding isolate not scoped to a particular Runtime.
+class HeapUsage {
+ final Map<String, dynamic> json;
+
+ HeapUsage(this.json);
+
+ /// Used heap size in bytes.
+ int get usedSize => json['usedSize'];
+
+ /// Allocated heap size in bytes.
+ int get totalSize => json['totalSize'];
+
+ @override
+ String toString() => '$usedSize of $totalSize';
+}
+
+/// Object property descriptor.
+class PropertyDescriptor {
+ final Map<String, dynamic> json;
+
+ PropertyDescriptor(this.json);
+
+ /// Property name or symbol description.
+ String get name => json['name'];
+
+ /// The value associated with the property.
+ RemoteObject get value =>
+ json['value'] != null ? RemoteObject(json['value']) : null;
+
+ /// True if the value associated with the property may be changed (data
+ /// descriptors only).
+ bool get writable => json['writable'];
+
+ /// True if the type of this property descriptor may be changed and if the
+ /// property may be deleted from the corresponding object.
+ bool get configurable => json['configurable'];
+
+ /// True if this property shows up during enumeration of the properties on the
+ /// corresponding object.
+ bool get enumerable => json['enumerable'];
+
+ /// True if the result was thrown during the evaluation.
+ bool get wasThrown => json['wasThrown'];
+
+ /// True if the property is owned for the object.
+ bool get isOwn => json['isOwn'];
+}
diff --git a/lib/webkit_inspection_protocol.dart b/lib/webkit_inspection_protocol.dart
index 3618974..1a0330e 100644
--- a/lib/webkit_inspection_protocol.dart
+++ b/lib/webkit_inspection_protocol.dart
@@ -239,12 +239,14 @@
}
class WipEvent {
+ final Map<String, dynamic> json;
+
final String method;
final Map<String, dynamic> params;
- WipEvent(Map<String, dynamic> map)
- : method = map['method'] as String,
- params = map['params'] as Map<String, dynamic>;
+ WipEvent(this.json)
+ : method = json['method'] as String,
+ params = json['params'] as Map<String, dynamic>;
String toString() => 'WipEvent: $method($params)';
}
@@ -322,18 +324,6 @@
}
}
-class WrappedWipEvent implements WipEvent {
- final WipEvent _wrapped;
-
- WrappedWipEvent(this._wrapped);
-
- @override
- String get method => _wrapped.method;
-
- @override
- Map<String, dynamic> get params => _wrapped.params;
-}
-
const _Experimental experimental = const _Experimental();
class _Experimental {
diff --git a/pubspec.yaml b/pubspec.yaml
index 76174a9..9dc68a5 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: webkit_inspection_protocol
-version: 0.6.0
+version: 0.7.0
description: A client for the Chrome DevTools Protocol (previously called the Webkit Inspection Protocol).
homepage: https://github.com/google/webkit_inspection_protocol.dart
diff --git a/test/data/runtime_test.html b/test/data/runtime_test.html
new file mode 100644
index 0000000..3f9d708
--- /dev/null
+++ b/test/data/runtime_test.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+</head>
+<body>
+<script language="JavaScript">
+ console.clear();
+ console.log('message 1');
+</script>
+
+</body>
+</html>
diff --git a/test/dom_model_test.dart b/test/dom_model_test.dart
index c7b63f1..762d128 100644
--- a/test/dom_model_test.dart
+++ b/test/dom_model_test.dart
@@ -124,6 +124,6 @@
expect(getAttributes, attributes);
expect(bodyNode.attributes, attributes);
- });
+ }, skip: 'google/webkit_inspection_protocol.dart/issues/52');
});
}
diff --git a/test/runtime_test.dart b/test/runtime_test.dart
new file mode 100644
index 0000000..4f4b78a
--- /dev/null
+++ b/test/runtime_test.dart
@@ -0,0 +1,96 @@
+// Copyright 2020 Google. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+@TestOn('vm')
+library wip.runtime_test;
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
+
+import 'test_setup.dart';
+
+void main() {
+ group('WipRuntime', () {
+ WipRuntime runtime;
+ List<StreamSubscription> subs = [];
+
+ setUp(() async {
+ runtime = (await wipConnection).runtime;
+ });
+
+ tearDown(() async {
+ await runtime.disable();
+ runtime = null;
+
+ await closeConnection();
+ subs.forEach((s) => s.cancel());
+ subs.clear();
+ });
+
+ test('getIsolateId', () async {
+ await runtime.enable();
+ await navigateToPage('runtime_test.html');
+
+ expect(await runtime.getIsolateId(), isNotEmpty);
+ });
+
+ test('getHeapUsage', () async {
+ await runtime.enable();
+ await navigateToPage('runtime_test.html');
+
+ HeapUsage usage = await runtime.getHeapUsage();
+
+ expect(usage.usedSize, greaterThan(0));
+ expect(usage.totalSize, greaterThan(0));
+ });
+
+ test('evaluate', () async {
+ await runtime.enable();
+ await navigateToPage('runtime_test.html');
+
+ RemoteObject result = await runtime.evaluate('1+1');
+ expect(result.type, 'number');
+ expect(result.value, 2);
+ });
+
+ test('callFunctionOn', () async {
+ await runtime.enable();
+ await navigateToPage('runtime_test.html');
+
+ RemoteObject console = await runtime.evaluate('console');
+ RemoteObject result = await runtime.callFunctionOn(
+ '''
+ function(msg) {
+ console.log(msg);
+ return msg;
+ }''',
+ objectId: console.objectId,
+ arguments: [
+ 'foo',
+ ],
+ );
+
+ expect(result.type, 'string');
+ expect(result.value, 'foo');
+ });
+
+ test('getProperties', () async {
+ await runtime.enable();
+ await navigateToPage('runtime_test.html');
+
+ RemoteObject console = await runtime.evaluate('console');
+
+ List<PropertyDescriptor> properties = await runtime.getProperties(
+ console,
+ ownProperties: true,
+ );
+
+ expect(properties, isNotEmpty);
+
+ PropertyDescriptor property = properties.first;
+ expect(property.name, isNotEmpty);
+ });
+ });
+}
diff --git a/test/test_setup.dart b/test/test_setup.dart
index 5f478b2..5a5cfbe 100644
--- a/test/test_setup.dart
+++ b/test/test_setup.dart
@@ -34,6 +34,10 @@
/// Starts ChromeDriver and returns the listening port.
Future<int> _startChromeDriver() async {
var chromeDriverPort = await findUnusedPort();
+
+ // Delay a small amount to allow us to close the above port.
+ await Future.delayed(const Duration(milliseconds: 25));
+
try {
var _exeExt = Platform.isWindows ? '.exe' : '';
_chromeDriver = await Process.start('chromedriver$_exeExt',