[VM] Remove observatory_2 directory and all references to it.

TEST=ci

Change-Id: I4e95e59fc909c01517ae59f39d04c38bb353b85a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/330525
Reviewed-by: Ben Konyi <bkonyi@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
This commit is contained in:
asiva 2023-10-16 17:45:46 +00:00 committed by Commit Queue
parent 312b46b444
commit e0fa7f9d0f
618 changed files with 1 additions and 78768 deletions

View file

@ -229,7 +229,6 @@ class Scrape {
if (entry.path.contains('/analyzer_cli/test/')) continue;
if (entry.path.contains('/compiler/test/')) continue;
if (entry.path.contains('/dart/runtime/observatory/tests/')) continue;
if (entry.path.contains('/dart/runtime/observatory_2/tests/')) continue;
if (entry.path.contains('/dart/runtime/tests/')) continue;
if (entry.path.contains('/dart/tests/')) continue;
if (entry.path.contains('/dev_compiler/test/')) continue;

View file

@ -21,8 +21,6 @@ const _legacyTestSelectors = [
'language_2',
'lib_2',
'kernel',
'observatory_ui_2',
'service_2',
'standalone_2',
'utils',
'vm',

View file

@ -31,8 +31,6 @@ final testSuiteDirectories = [
Path('pkg'),
Path('runtime/observatory/tests/observatory_ui'),
Path('runtime/observatory/tests/service'),
Path('runtime/observatory_2/tests/observatory_ui_2'),
Path('runtime/observatory_2/tests/service_2'),
Path('runtime/tests/vm'),
Path('samples'),
Path('tests/corelib'),

View file

@ -739,7 +739,7 @@ class StandardTestSuite extends TestSuite {
_enqueueStandardTest(testFile, expectationSet, onTest);
} else if (configuration.runtime.isBrowser) {
_enqueueBrowserTest(testFile, expectationSet, onTest);
} else if (suiteName == 'service' || suiteName == 'service_2') {
} else if (suiteName == 'service') {
_enqueueServiceTest(testFile, expectationSet, onTest);
} else {
_enqueueStandardTest(testFile, expectationSet, onTest);

View file

@ -116,9 +116,7 @@ void testSelectors() {
'vm',
'utils',
'lib_2',
'service_2',
'kernel',
'observatory_ui_2',
'ffi_2',
}, configuration.selectors.keys, "suites for $arguments");
}

View file

@ -1,5 +0,0 @@
bootstrap_css
out
build
.pub
.idea

View file

@ -1,261 +0,0 @@
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../../build/dart/copy_tree.gni")
import("../../build/dart/dart_action.gni")
import("observatory_sources.gni")
prebuilt_dart_action("build_observatory") {
visibility = [ ":copy_main_dart_js" ]
# dart2js produces a .deps file, but it is not in a format that is understood
# by ninja, so we explicitly list all the sources here.
inputs = [ "../../.dart_tool/package_config.json" ] + observatory_sources
output = "$target_gen_dir/observatory/web/main.dart.js"
outputs = [ output ]
if (is_debug) {
outputs += [ "$target_gen_dir/observatory/web/main.dart.js.map" ]
}
args = [
"compile",
"js",
"-o",
rebase_path(output),
"--packages=" + rebase_path("../../.dart_tool/package_config.json"),
rebase_path("web/main.dart"),
]
if (is_debug) {
args += [ "--enable-asserts" ]
} else {
args += [ "--minify" ]
}
}
# The rules here down to "deploy_observatory" copy files into place such that
# they can be packaged into a tar file. These rules do the following copies:
#
# web/* ->
# $target_out_dir/observatory/deployed/web
# $target_gen_dir/observatory/web/main.dart.js ->
# $target_out_dir/observatory/deployed/web/main.dart.js
# ../../third_party/observatory_pub_packages/packages/$PACKAGE/lib/* ->
# $target_out_dir/observatory/deployed/web/packages/$PACKAGE
# lib/* ->
# $target_out_dir/observatory/deployed/web/packages/observatory
#
# Files matching "observatory_ignore_patterns" are excluded.
# Files matching these patterns are filtered out of the Observatory assets.
observatory_ignore_patterns = [
# "\$sdk", this is the first element concatenated into the string below.
"*.concat.js",
"*.dart",
"*.log",
"*.precompiled.js",
"*.scriptUrls",
"*_buildLogs*",
"*~",
"CustomElements.*",
"HTMLImports.*",
"MutationObserver.*",
"ShadowDOM.*",
"bower.json",
"dart_support.*",
"interop_support.*",
"package.json",
"unittest*",
]
if (!is_debug) {
observatory_ignore_patterns += [ "*.map" ]
}
# The ignore_patterns entry in the scopes accepted by copy_trees() is a
# string of comma delimited patterns.
observatory_ignore_string = "\$sdk"
foreach(pattern, observatory_ignore_patterns) {
observatory_ignore_string = "$observatory_ignore_string,$pattern"
}
copy_tree_specs = []
copy_tree_specs += [
{
target = "copy_web_package"
visibility = [ ":deploy_observatory" ]
source = "web"
dest = "$target_out_dir/observatory/deployed/web"
ignore_patterns = observatory_ignore_string
},
]
copy_tree_specs += [
{
target = "copy_observatory_package"
visibility = [ ":deploy_observatory" ]
source = "lib"
dest = "$target_out_dir/observatory/deployed/web/packages/observatory"
ignore_patterns = observatory_ignore_string
},
]
# This is not a rule, rather, it generates rules with names of the form:
# "copy_$package_package" for the packages in observatory_pub_packages.
copy_trees("copy_observatory_packages") {
sources = copy_tree_specs
}
copy("copy_main_dart_js") {
visibility = [ ":deploy_observatory" ]
deps = [ ":build_observatory" ]
sources = [ "$target_gen_dir/observatory/web/main.dart.js" ]
if (is_debug) {
sources += [ "$target_gen_dir/observatory/web/main.dart.js.map" ]
}
outputs = [ "$target_out_dir/observatory/deployed/web/{{source_file_part}}" ]
}
group("deploy_observatory") {
deps = [
":copy_main_dart_js",
":copy_observatory_package",
":copy_web_package",
]
}
template("observatory_archive") {
enable_compression = false
if (defined(invoker.compress) && invoker.compress) {
enable_compression = true
}
action(target_name) {
deps = [ ":deploy_observatory" ]
output_name = target_name
output = "$target_gen_dir/${output_name}.tar"
outputs = [ output ]
script = "../tools/create_archive.py"
args = [
"--tar_output",
rebase_path(output),
"--client_root",
rebase_path("$target_out_dir/observatory/deployed/web/"),
]
if (enable_compression) {
args += [ "--compress" ]
}
}
}
observatory_archive("compressed_observatory_archive") {
compress = true
}
copy("copy_compressed_observatory_archive") {
archive_target = ":compressed_observatory_archive"
deps = [ archive_target ]
archive_dir = get_label_info(archive_target, "target_gen_dir")
archive_name = get_label_info(archive_target, "name")
archive_file = "${archive_dir}/${archive_name}.tar"
sources = [ archive_file ]
outputs = [ "$root_out_dir/${archive_name}.tar" ]
}
observatory_archive("observatory_archive") {
compress = false
}
copy("copy_observatory_archive") {
archive_target = ":observatory_archive"
deps = [ archive_target ]
archive_dir = get_label_info(archive_target, "target_gen_dir")
archive_name = get_label_info(archive_target, "name")
archive_file = "${archive_dir}/${archive_name}.tar"
sources = [ archive_file ]
outputs = [ "$root_out_dir/${archive_name}.tar" ]
}
# Generates a .cc file containing the bytes of the observatory archive in a C
# array.
#
# Parameters:
# inner_namespace (required):
# The inner C++ namespace that the C array lives in.
#
# outer_namespace (required):
# The outer C++ namespace that the C array lives in.
#
# archive_file (required):
# The path to the observatory archive.
#
template("observatory_archive_source") {
assert(defined(invoker.inner_namespace),
"Need inner_namespace in $target_name")
assert(defined(invoker.outer_namespace),
"Need outer_namespace in $target_name")
assert(defined(invoker.archive_file), "Need archive_file in $target_name")
action(target_name) {
forward_variables_from(invoker, [ "deps" ])
inputs = [ invoker.archive_file ]
output = "$target_gen_dir/${target_name}.cc"
outputs = [ output ]
script = "../tools/create_archive.py"
args = [
"--tar_input",
rebase_path(invoker.archive_file),
"--output",
rebase_path(output),
"--outer_namespace",
invoker.outer_namespace,
"--inner_namespace",
invoker.inner_namespace,
"--name",
"observatory_assets_archive",
]
}
}
observatory_archive_source("embedded_archive_observatory") {
outer_namespace = "dart"
inner_namespace = "observatory"
# TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
archive_target = ":observatory_archive"
deps = [ archive_target ]
archive_dir = get_label_info(archive_target, "target_gen_dir")
archive_name = get_label_info(archive_target, "name")
archive_file = "${archive_dir}/${archive_name}.tar"
}
source_set("embedded_observatory_archive") {
deps = [ ":embedded_archive_observatory" ]
sources = [ rebase_path("$target_gen_dir/embedded_archive_observatory.cc") ]
}
observatory_archive_source("standalone_archive_observatory") {
outer_namespace = "dart"
inner_namespace = "bin"
# TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
archive_target = ":compressed_observatory_archive"
deps = [ archive_target ]
archive_dir = get_label_info(archive_target, "target_gen_dir")
archive_name = get_label_info(archive_target, "name")
archive_file = "${archive_dir}/${archive_name}.tar"
}
source_set("standalone_observatory_archive") {
deps = [ ":standalone_archive_observatory" ]
sources = [ rebase_path("$target_gen_dir/standalone_archive_observatory.cc") ]
}

View file

@ -1,174 +0,0 @@
# Hacking Observatory
These instructions will guide you through the Observatory development and
testing workflow.
## SDK Setup & Build
Getting ready to start.
Before you start to hack on Observatory, follow the [instructions][build_sdk] to
have a working environment in which you are able to build and test the Dart SDK.
## Run existing tests
Before hacking Observatory let's run the existing Observatory tests.
We suggest to run all the test in __debug__ mode.
First build the sdk in debug mode
```
$ ./tools/build.py --mode debug create_sdk
```
From the root of the sdk repository run:
```
$ ./tools/test.py -mdebug service
```
## Serve Observatory
Observatory is built as part of building the sdk. Previously, it was recommended
to run the Observatory using `pub serve` to avoid having to rebuild the sdk for
each change to Observatory. However, `pub serve` was deprecated as part of the
transition to Dart 2.0.
[Issue #35678](https://github.com/dart-lang/sdk/issues/35678)
tracks changes required to allow for `package:build_runner` to run Observatory
without having to rebuild the sdk after each change.
## Connect to a VM
Start a Dart VM with the ``--observe`` flag (as explained in the
[get started guide][observatory_get_started]) and connect your Observatory
instance to that VM.
Example script (file name ```clock.dart```):
```dart
import 'dart:async' show Timer, Duration;
main() {
bool tick = true;
new Timer.periodic(const Duration(seconds: 1), (Timer t) {
print(tick ? 'tick' : 'tock');
tick = !tick;
});
}
```
Start the script:
```
$ dart --disable-service-origin-check --observe clock.dart
```
## Code Reviews
The development workflow of Dart (and Observatory) is based on code reviews.
Follow the code review [instructions][code_review] to be able to successfully
submit your code.
The main reviewers for Observatory related CLs are:
- asiva
- bkonyi
- rmacnak
## Write a new service test
All the service tests are located in the ```tests/service``` folder.
Test file names follow the convention ```<description>_test.dart```
(e.g. ```a_brief_description_test.dart```).
The test is generally structured in the following way.
```dart
import 'package:test/test.dart';
main() {
// Some code that you need to test.
var a = 1 + 2;
// Some assertions to check the results.
expect(a, equal(3));
}
```
See the official [test library][test_library] instructions;
The ```test_helper.dart``` file expose some functions that allow to run a part
of the code into another __VM__.
To test synchronous operations:
```dart
import 'test_helper.dart';
code() {
// Write the code you want to be execute into another VM.
}
var tests = [
// A series of tests that you want to run against the above code.
(Isolate isolate) async {
await isolate.reload();
// Use the isolate to communicate to the VM.
}
];
main(args) => runIsolateTestsSynchronous(args,
tests,
testeeConcurrent: code);
```
In order to test asynchronous operations:
```dart
import 'test_helper.dart';
code() async {
// Write the asynchronous code you want to be execute into another VM.
}
var tests = [
// A series of tests that you want to run against the above code.
(Isolate isolate) async {
await isolate.reload();
// Use the isolate to communicate to the VM.
}
];
main(args) async => runIsolateTests(args,
tests,
testeeConcurrent: code);
```
Both ```runIsolateTests``` and ```runIsolateTestsSynchronous``` have the
following named parameters:
- __testeeBefore__ (void()) a function that is going to be executed before
the test
- __testeeConcurrent__ (void()) test that is going to be executed
- __pause_on_start__ (bool, default: false) pause the Isolate before the first
instruction
- __pause_on_exit__ (bool, default: false) pause the Isolate after the last
instruction
- __pause_on_unhandled_exceptions__ (bool, default: false) pause the Isolate at
an unhandled exception
- __trace_service__ (bool, default: false) trace VM service requests
- __trace_compiler__ (bool, default: false) trace compiler operations
- __verbose_vm__ (bool, default: false) verbose logging
Some common and reusable test are available from ```service_test_common.dart```:
- hasPausedFor
- hasStoppedAtBreakpoint
- hasStoppedWithUnhandledException
- hasStoppedAtExit
- hasPausedAtStartcode_review
and utility functions:
- subscribeToStream
- cancelStreamSubscription
- asyncStepOver
- setBreakpointAtLine
- resumeIsolate
- resumeAndAwaitEvent
- resumeIsolateAndAwaitEvent
- stepOver
- getClassFromRootLib
- rootLibraryFieldValue
## Run your tests
See: __Run existing tests__
[build_sdk]: https://github.com/dart-lang/sdk/wiki/Building "Building the Dart SDK"
[open_observatory]: http://localhost:8080/ "Open Observatory"
[observatory_get_started]: https://dart-lang.github.io/observatory/get-started.html "Observatory get started"
[code_review]: https://github.com/dart-lang/sdk/wiki/Code-review-workflow-with-GitHub-and-reitveld "Code Review"
[test_library]: https://pub.dartlang.org/packages/test "Test Library"

View file

@ -1,16 +0,0 @@
analyzer:
errors:
dead_code: ignore
unused_local_variable: ignore
exclude:
- tests/service/bad_reload/v2/main.dart
- tests/service/complex_reload/v2/main.dart
- tests/service/developer_extension_test.dart
- tests/service/evaluate_activation_in_method_class_test.dart
- tests/service/get_user_level_retaining_path_rpc_test.dart
- tests/service/pause_on_unhandled_async_exceptions_test.dart
linter:
rules:
- prefer_final_fields
- prefer_final_locals

View file

@ -1,421 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// A way to test heap snapshot loading and analysis outside of Observatory, and
// to handle snapshots that require more memory to analyze than is available in
// a web browser.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:observatory_2/object_graph.dart';
Future<SnapshotGraph> load(String uri) async {
final ws = await WebSocket.connect(uri,
compression: CompressionOptions.compressionOff);
final getVM = new Completer<String>();
final reader = new SnapshotReader();
reader.onProgress.listen(print);
ws.listen((dynamic response) {
if (response is String) {
response = json.decode(response);
if (response['id'] == 1) {
getVM.complete(response['result']['isolates'][0]['id']);
}
} else if (response is List<int>) {
response = new Uint8List.fromList(response);
final dataOffset =
new ByteData.view(response.buffer).getUint32(0, Endian.little);
dynamic metadata = new Uint8List.view(response.buffer, 4, dataOffset - 4);
final data = new Uint8List.view(
response.buffer, dataOffset, response.length - dataOffset);
metadata = utf8.decode(metadata);
metadata = json.decode(metadata);
var event = metadata['params']['event'];
if (event['kind'] == 'HeapSnapshot') {
bool last = event['last'] == true;
reader.add(data);
if (last) {
reader.close();
ws.close();
}
}
}
});
ws.add(json.encode({
'jsonrpc': '2.0',
'method': 'getVM',
'params': {},
'id': 1,
}));
final String isolateId = await getVM.future;
ws.add(json.encode({
'jsonrpc': '2.0',
'method': 'streamListen',
'params': {'streamId': 'HeapSnapshot'},
'id': 2,
}));
ws.add(json.encode({
'jsonrpc': '2.0',
'method': 'requestHeapSnapshot',
'params': {'isolateId': isolateId},
'id': 3,
}));
return reader.done;
}
String makeData(dynamic root) {
// 'root' can be arbitrarily deep, so we can't directly represent it as a
// JSON tree, which cause a stack overflow here encoding it and in the JS
// engine decoding it. Instead we flatten the tree into a list of tuples with
// a parent pointer and re-inflate it in JS.
final indices = <dynamic, int>{};
final preorder = <dynamic>[];
preorder.add(root);
for (var index = 0; index < preorder.length; index++) {
final object = preorder[index];
preorder.addAll(object.children);
}
final flattened = <dynamic>[];
for (var index = 0; index < preorder.length; index++) {
final object = preorder[index];
indices[object] = index;
flattened.add(object.description);
flattened.add(object.klass.name);
flattened.add(object.retainedSize);
if (index == 0) {
flattened.add(null);
} else {
flattened.add(indices[object.parent]);
}
}
return json.encode(flattened);
}
var css = '''
.treemapTile {
position: absolute;
box-sizing: border-box;
border: solid 1px;
font-size: 10;
text-align: center;
overflow: hidden;
white-space: nowrap;
cursor: default;
}
''';
var js = '''
function hash(string) {
// Jenkin's one_at_a_time.
let h = string.length;
for (let i = 0; i < string.length; i++) {
h += string.charCodeAt(i);
h += h << 10;
h ^= h >> 6;
}
h += h << 3;
h ^= h >> 11;
h += h << 15;
return h;
}
function color(string) {
let hue = hash(string) % 360;
return "hsl(" + hue + ",60%,60%)";
}
function prettySize(size) {
if (size < 1024) return size + "B";
size /= 1024;
if (size < 1024) return size.toFixed(1) + "KiB";
size /= 1024;
if (size < 1024) return size.toFixed(1) + "MiB";
size /= 1024;
return size.toFixed(1) + "GiB";
}
function prettyPercent(fraction) {
return (fraction * 100).toFixed(1);
}
function createTreemapTile(v, width, height, depth) {
let div = document.createElement("div");
div.className = "treemapTile";
div.style["background-color"] = color(v.type);
div.ondblclick = function(event) {
event.stopPropagation();
if (depth == 0) {
let dom = v.parent;
if (dom == undefined) {
// Already at root.
} else {
showDominatorTree(dom); // Zoom out.
}
} else {
showDominatorTree(v); // Zoom in.
}
};
let left = 0;
let top = 0;
const kPadding = 5;
const kBorder = 1;
left += kPadding - kBorder;
top += kPadding - kBorder;
width -= 2 * kPadding;
height -= 2 * kPadding;
let label = v.name + " [" + prettySize(v.size) + "]";
div.title = label;
if (width < 10 || height < 10) {
// Too small: don't render label or children.
return div;
}
div.appendChild(document.createTextNode(label));
const kLabelHeight = 9;
top += kLabelHeight;
height -= kLabelHeight;
if (depth > 2) {
// Too deep: don't render children.
return div;
}
if (width < 4 || height < 4) {
// Too small: don't render children.
return div;
}
let children = new Array();
v.children.forEach(function(c) {
// Size 0 children seem to confuse the layout algorithm (accumulating
// rounding errors?).
if (c.size > 0) {
children.push(c);
}
});
children.sort(function (a, b) {
return b.size - a.size;
});
const scale = width * height / v.size;
// Bruls M., Huizing K., van Wijk J.J. (2000) Squarified Treemaps. In: de
// Leeuw W.C., van Liere R. (eds) Data Visualization 2000. Eurographics.
// Springer, Vienna.
for (let rowStart = 0; // Index of first child in the next row.
rowStart < children.length;) {
// Prefer wider rectangles, the better to fit text labels.
const GOLDEN_RATIO = 1.61803398875;
let verticalSplit = (width / height) > GOLDEN_RATIO;
let space;
if (verticalSplit) {
space = height;
} else {
space = width;
}
let rowMin = children[rowStart].size * scale;
let rowMax = rowMin;
let rowSum = 0;
let lastRatio = 0;
let rowEnd; // One after index of last child in the next row.
for (rowEnd = rowStart; rowEnd < children.length; rowEnd++) {
let size = children[rowEnd].size * scale;
if (size < rowMin) rowMin = size;
if (size > rowMax) rowMax = size;
rowSum += size;
let ratio = Math.max((space * space * rowMax) / (rowSum * rowSum),
(rowSum * rowSum) / (space * space * rowMin));
if ((lastRatio != 0) && (ratio > lastRatio)) {
// Adding the next child makes the aspect ratios worse: remove it and
// add the row.
rowSum -= size;
break;
}
lastRatio = ratio;
}
let rowLeft = left;
let rowTop = top;
let rowSpace = rowSum / space;
for (let i = rowStart; i < rowEnd; i++) {
let child = children[i];
let size = child.size * scale;
let childWidth;
let childHeight;
if (verticalSplit) {
childWidth = rowSpace;
childHeight = size / childWidth;
} else {
childHeight = rowSpace;
childWidth = size / childHeight;
}
let childDiv = createTreemapTile(child, childWidth, childHeight, depth + 1);
childDiv.style.left = rowLeft + "px";
childDiv.style.top = rowTop + "px";
// Oversize the final div by kBorder to make the borders overlap.
childDiv.style.width = (childWidth + kBorder) + "px";
childDiv.style.height = (childHeight + kBorder) + "px";
div.appendChild(childDiv);
if (verticalSplit)
rowTop += childHeight;
else
rowLeft += childWidth;
}
if (verticalSplit) {
left += rowSpace;
width -= rowSpace;
} else {
top += rowSpace;
height -= rowSpace;
}
rowStart = rowEnd;
}
return div;
}
function setBody(div) {
let body = document.body;
while (body.firstChild) {
body.removeChild(body.firstChild);
}
body.appendChild(div);
}
function showDominatorTree(v) {
let header = document.createElement("div");
header.textContent = "Dominator Tree";
header.title =
"Double click a box to zoom in.\\n" +
"Double click the outermost box to zoom out.";
header.className = "headerRow";
header.style["flex-grow"] = 0;
header.style["padding"] = "5px";
header.style["border-bottom"] = "solid 1px";
let content = document.createElement("div");
content.style["flex-basis"] = 0;
content.style["flex-grow"] = 1;
let column = document.createElement("div");
column.style["width"] = "100%";
column.style["height"] = "100%";
column.style["border"] = "solid 2px";
column.style["display"] = "flex";
column.style["flex-direction"] = "column";
column.appendChild(header);
column.appendChild(content);
setBody(column);
// Add the content div to the document first so the browser will calculate
// the available width and height.
let w = content.offsetWidth;
let h = content.offsetHeight;
let topTile = createTreemapTile(v, w, h, 0);
topTile.style.width = w;
topTile.style.height = h;
topTile.style.border = "none";
content.appendChild(topTile);
}
function inflateData(flattened) {
// 'root' can be arbitrarily deep, so we need to use an explicit stack
// instead of the call stack.
let nodes = new Array();
let i = 0;
while (i < flattened.length) {
let node = {
"name": flattened[i++],
"type": flattened[i++],
"size": flattened[i++],
"children": [],
"parent": null
};
nodes.push(node);
let parentIndex = flattened[i++];
if (parentIndex != null) {
let parent = nodes[parentIndex];
parent.children.push(node);
node.parent = parent;
}
}
return nodes[0];
}
var root = __DATA__;
root = inflateData(root);
showDominatorTree(root);
''';
var html = '''
<html>
<head>
<title>Dart Heap Snapshot</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>$css</style>
</head>
<body>
<script>$js</script>
</body>
</html>
''';
main(List<String> args) async {
if (args.length < 1) {
print('Usage: heap_snapshot.dart <vm-service-uri>');
exitCode = 1;
return;
}
var uri = Uri.parse(args[0]);
if (uri.isScheme('http')) {
uri = uri.replace(scheme: 'ws');
} else if (uri.isScheme('https')) {
uri = uri.replace(scheme: 'wss');
}
if (!uri.path.endsWith('/ws')) {
uri = uri.resolve('ws');
}
final snapshot = await load(uri.toString());
final dir = await Directory.systemTemp.createTemp('heap-snapshot');
final path = dir.path + '/merged-dominator.html';
final file = await File(path).create();
final tree = makeData(snapshot.mergedRoot);
await file.writeAsString(html.replaceAll('__DATA__', tree));
print('Wrote file://' + path);
}

View file

@ -1,37 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library shell;
import 'package:observatory_2/service_io.dart';
import 'dart:io';
// Simple demo for service_io library. Connects to localhost on the default
// port, picks the first isolate, reads requests from stdin, and prints
// results to stdout. Example session:
// <<< isolate isolates/1071334835
// >>> /classes/40
// <<< {"type":"Class","id":"classes\/40","name":"num","user_name":"num",...
// >>> /objects/0
// >>> {"type":"Array","class":{"type":"@Class","id":"classes\/62",...
void repl(VM vm, Isolate isolate, String lastResult) {
print(lastResult);
Map params = {
'objectId': stdin.readLineSync(),
};
isolate.invokeRpcNoUpgrade('getObject', params).then((Map result) {
repl(vm, isolate, result.toString());
});
}
void main() {
String addr = 'ws://localhost:8181/ws';
new WebSocketVM(new WebSocketVMTarget(addr)).load().then((serviceObject) {
VM vm = serviceObject;
Isolate isolate = vm.isolates.first;
repl(vm, isolate, 'isolate ${isolate.id}');
});
}

View file

@ -1,10 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library allocation_profiler;
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart' as S;
part 'src/allocation_profile/allocation_profile.dart';

View file

@ -1,28 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library app;
import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'package:logging/logging.dart';
import 'package:observatory_2/service_html.dart';
import 'package:observatory_2/elements.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/event.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/repositories.dart';
import 'package:observatory_2/tracer.dart';
import 'package:stack_trace/stack_trace.dart';
export 'package:observatory_2/utils.dart';
part 'src/app/application.dart';
part 'src/app/location_manager.dart';
part 'src/app/notification.dart';
part 'src/app/page.dart';
part 'src/app/settings.dart';
part 'src/app/view_model.dart';

View file

@ -1,9 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library cli;
import 'dart:async';
part 'src/cli/command.dart';

View file

@ -1,12 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library debugger;
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart';
part 'src/debugger/debugger.dart';
part 'src/debugger/debugger_location.dart';

View file

@ -1,98 +0,0 @@
library observatory_elements;
export 'package:observatory_2/src/elements/allocation_profile.dart';
export 'package:observatory_2/src/elements/class_allocation_profile.dart';
export 'package:observatory_2/src/elements/class_instances.dart';
export 'package:observatory_2/src/elements/class_ref.dart';
export 'package:observatory_2/src/elements/class_tree.dart';
export 'package:observatory_2/src/elements/class_view.dart';
export 'package:observatory_2/src/elements/code_ref.dart';
export 'package:observatory_2/src/elements/code_view.dart';
export 'package:observatory_2/src/elements/containers/search_bar.dart';
export 'package:observatory_2/src/elements/containers/virtual_collection.dart';
export 'package:observatory_2/src/elements/containers/virtual_tree.dart';
export 'package:observatory_2/src/elements/context_ref.dart';
export 'package:observatory_2/src/elements/context_view.dart';
export 'package:observatory_2/src/elements/cpu_profile.dart';
export 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
export 'package:observatory_2/src/elements/cpu_profile_table.dart';
export 'package:observatory_2/src/elements/curly_block.dart';
export 'package:observatory_2/src/elements/debugger.dart';
export 'package:observatory_2/src/elements/error_ref.dart';
export 'package:observatory_2/src/elements/error_view.dart';
export 'package:observatory_2/src/elements/eval_box.dart';
export 'package:observatory_2/src/elements/field_ref.dart';
export 'package:observatory_2/src/elements/field_view.dart';
export 'package:observatory_2/src/elements/flag_list.dart';
export 'package:observatory_2/src/elements/function_ref.dart';
export 'package:observatory_2/src/elements/function_view.dart';
export 'package:observatory_2/src/elements/general_error.dart';
export 'package:observatory_2/src/elements/heap_map.dart';
export 'package:observatory_2/src/elements/heap_snapshot.dart';
export 'package:observatory_2/src/elements/process_snapshot.dart';
export 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
export 'package:observatory_2/src/elements/icdata_ref.dart';
export 'package:observatory_2/src/elements/icdata_view.dart';
export 'package:observatory_2/src/elements/instance_ref.dart';
export 'package:observatory_2/src/elements/instance_view.dart';
export 'package:observatory_2/src/elements/isolate/counter_chart.dart';
export 'package:observatory_2/src/elements/isolate/location.dart';
export 'package:observatory_2/src/elements/isolate/run_state.dart';
export 'package:observatory_2/src/elements/isolate/shared_summary.dart';
export 'package:observatory_2/src/elements/isolate/summary.dart';
export 'package:observatory_2/src/elements/isolate_reconnect.dart';
export 'package:observatory_2/src/elements/isolate_ref.dart';
export 'package:observatory_2/src/elements/isolate_view.dart';
export 'package:observatory_2/src/elements/json_view.dart';
export 'package:observatory_2/src/elements/library_ref.dart';
export 'package:observatory_2/src/elements/library_view.dart';
export 'package:observatory_2/src/elements/local_var_descriptors_ref.dart';
export 'package:observatory_2/src/elements/logging.dart';
export 'package:observatory_2/src/elements/megamorphiccache_ref.dart';
export 'package:observatory_2/src/elements/megamorphiccache_view.dart';
export 'package:observatory_2/src/elements/metric/details.dart';
export 'package:observatory_2/src/elements/metric/graph.dart';
export 'package:observatory_2/src/elements/metrics.dart';
export 'package:observatory_2/src/elements/native_memory_profiler.dart';
export 'package:observatory_2/src/elements/nav/class_menu.dart';
export 'package:observatory_2/src/elements/nav/isolate_menu.dart';
export 'package:observatory_2/src/elements/nav/library_menu.dart';
export 'package:observatory_2/src/elements/nav/menu_item.dart';
export 'package:observatory_2/src/elements/nav/notify.dart';
export 'package:observatory_2/src/elements/nav/notify_event.dart';
export 'package:observatory_2/src/elements/nav/notify_exception.dart';
export 'package:observatory_2/src/elements/nav/refresh.dart';
export 'package:observatory_2/src/elements/nav/top_menu.dart';
export 'package:observatory_2/src/elements/nav/vm_menu.dart';
export 'package:observatory_2/src/elements/object_common.dart';
export 'package:observatory_2/src/elements/object_view.dart';
export 'package:observatory_2/src/elements/objectpool_ref.dart';
export 'package:observatory_2/src/elements/objectpool_view.dart';
export 'package:observatory_2/src/elements/objectstore_view.dart';
export 'package:observatory_2/src/elements/observatory_application.dart';
export 'package:observatory_2/src/elements/pc_descriptors_ref.dart';
export 'package:observatory_2/src/elements/persistent_handles.dart';
export 'package:observatory_2/src/elements/ports.dart';
export 'package:observatory_2/src/elements/sample_buffer_control.dart';
export 'package:observatory_2/src/elements/script_inset.dart';
export 'package:observatory_2/src/elements/script_ref.dart';
export 'package:observatory_2/src/elements/script_view.dart';
export 'package:observatory_2/src/elements/sentinel_value.dart';
export 'package:observatory_2/src/elements/sentinel_view.dart';
export 'package:observatory_2/src/elements/singletargetcache_ref.dart';
export 'package:observatory_2/src/elements/singletargetcache_view.dart';
export 'package:observatory_2/src/elements/source_inset.dart';
export 'package:observatory_2/src/elements/source_link.dart';
export 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
export 'package:observatory_2/src/elements/strongly_reachable_instances.dart';
export 'package:observatory_2/src/elements/subtypetestcache_ref.dart';
export 'package:observatory_2/src/elements/subtypetestcache_view.dart';
export 'package:observatory_2/src/elements/timeline/dashboard.dart';
export 'package:observatory_2/src/elements/timeline_page.dart';
export 'package:observatory_2/src/elements/type_arguments_ref.dart';
export 'package:observatory_2/src/elements/unknown_ref.dart';
export 'package:observatory_2/src/elements/unlinkedcall_ref.dart';
export 'package:observatory_2/src/elements/unlinkedcall_view.dart';
export 'package:observatory_2/src/elements/vm_connect.dart';
export 'package:observatory_2/src/elements/vm_connect_target.dart';
export 'package:observatory_2/src/elements/vm_view.dart';

View file

@ -1,380 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:logging/logging.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart' as S;
class VMUpdateEvent implements M.VMUpdateEvent {
final DateTime timestamp;
final M.VMRef vm;
VMUpdateEvent(this.timestamp, this.vm) {
assert(timestamp != null);
assert(vm != null);
}
}
class IsolateStartEvent implements M.IsolateStartEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
IsolateStartEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class IsolateRunnableEvent implements M.IsolateRunnableEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
IsolateRunnableEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class IsolateExitEvent implements M.IsolateExitEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
IsolateExitEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class IsolateUpdateEvent implements M.IsolateUpdateEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
IsolateUpdateEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class IsolateReloadEvent implements M.IsolateReloadEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.ErrorRef error;
IsolateReloadEvent(this.timestamp, this.isolate, this.error) {
assert(timestamp != null);
assert(isolate != null);
assert(error != null);
}
}
class ServiceExtensionAddedEvent implements M.ServiceExtensionAddedEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final String extensionRPC;
ServiceExtensionAddedEvent(this.timestamp, this.isolate, this.extensionRPC) {
assert(timestamp != null);
assert(isolate != null);
assert(extensionRPC != null);
}
}
class DebuggerSettingsUpdateEvent implements M.DebuggerSettingsUpdateEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
DebuggerSettingsUpdateEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class PauseStartEvent implements M.PauseStartEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
PauseStartEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class PauseExitEvent implements M.PauseExitEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
PauseExitEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class PauseBreakpointEvent implements M.PauseBreakpointEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final Iterable<M.Breakpoint> pauseBreakpoints;
final M.Frame topFrame;
final bool atAsyncSuspension;
/// [optional]
final M.Breakpoint breakpoint;
PauseBreakpointEvent(
this.timestamp,
this.isolate,
Iterable<M.Breakpoint> pauseBreakpoints,
this.topFrame,
this.atAsyncSuspension,
[this.breakpoint])
: pauseBreakpoints = new List.unmodifiable(pauseBreakpoints) {
assert(timestamp != null);
assert(isolate != null);
assert(pauseBreakpoints != null);
assert(topFrame != null);
assert(atAsyncSuspension != null);
}
}
class PauseInterruptedEvent implements M.PauseInterruptedEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Frame topFrame;
final bool atAsyncSuspension;
PauseInterruptedEvent(
this.timestamp, this.isolate, this.topFrame, this.atAsyncSuspension) {
assert(timestamp != null);
assert(isolate != null);
assert(atAsyncSuspension != null);
}
}
class PausePostRequestEvent implements M.PausePostRequestEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Frame topFrame;
final bool atAsyncSuspension;
PausePostRequestEvent(
this.timestamp, this.isolate, this.topFrame, this.atAsyncSuspension) {
assert(timestamp != null);
assert(isolate != null);
assert(atAsyncSuspension != null);
}
}
class PauseExceptionEvent implements M.PauseExceptionEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Frame topFrame;
final M.InstanceRef exception;
PauseExceptionEvent(
this.timestamp, this.isolate, this.topFrame, this.exception) {
assert(timestamp != null);
assert(isolate != null);
assert(topFrame != null);
assert(exception != null);
}
}
class ResumeEvent implements M.ResumeEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Frame topFrame;
ResumeEvent(this.timestamp, this.isolate, this.topFrame) {
assert(timestamp != null);
assert(isolate != null);
}
}
class BreakpointAddedEvent implements M.BreakpointAddedEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Breakpoint breakpoint;
BreakpointAddedEvent(this.timestamp, this.isolate, this.breakpoint) {
assert(timestamp != null);
assert(isolate != null);
assert(breakpoint != null);
}
}
class BreakpointResolvedEvent implements M.BreakpointResolvedEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Breakpoint breakpoint;
BreakpointResolvedEvent(this.timestamp, this.isolate, this.breakpoint) {
assert(timestamp != null);
assert(isolate != null);
assert(breakpoint != null);
}
}
class BreakpointRemovedEvent implements M.BreakpointRemovedEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.Breakpoint breakpoint;
BreakpointRemovedEvent(this.timestamp, this.isolate, this.breakpoint) {
assert(timestamp != null);
assert(isolate != null);
assert(breakpoint != null);
}
}
class InspectEvent implements M.InspectEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final M.InstanceRef inspectee;
InspectEvent(this.timestamp, this.isolate, this.inspectee) {
assert(timestamp != null);
assert(isolate != null);
assert(inspectee != null);
}
}
class NoneEvent implements M.NoneEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
NoneEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class GCEvent implements M.GCEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
GCEvent(this.timestamp, this.isolate) {
assert(timestamp != null);
assert(isolate != null);
}
}
class LoggingEvent implements M.LoggingEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final Map logRecord;
LoggingEvent(this.timestamp, this.isolate, this.logRecord) {
assert(timestamp != null);
assert(isolate != null);
assert(logRecord != null);
}
}
class ExtensionEvent implements M.ExtensionEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final String extensionKind;
final M.ExtensionData extensionData;
ExtensionEvent(
this.timestamp, this.isolate, this.extensionKind, this.extensionData) {
assert(timestamp != null);
assert(isolate != null);
assert(extensionKind != null);
assert(extensionData != null);
}
}
class TimelineEventsEvent implements M.TimelineEventsEvent {
final DateTime timestamp;
final M.IsolateRef isolate;
final Iterable<M.TimelineEvent> timelineEvents;
TimelineEventsEvent(
this.timestamp, this.isolate, Iterable<M.TimelineEvent> timelineEvents)
: timelineEvents = new List.unmodifiable(timelineEvents) {
assert(timestamp != null);
assert(isolate != null);
assert(timelineEvents != null);
}
}
class ConnectionClosedEvent implements M.ConnectionClosedEvent {
final DateTime timestamp;
final String reason;
ConnectionClosedEvent(this.timestamp, this.reason) {
assert(timestamp != null);
assert(reason != null);
}
}
class ServiceRegisteredEvent implements M.ServiceRegisteredEvent {
final DateTime timestamp;
final String service;
final String method;
final String alias;
ServiceRegisteredEvent(
this.timestamp, this.service, this.method, this.alias) {
assert(timestamp != null);
assert(service != null);
assert(method != null);
assert(alias != null);
}
}
class ServiceUnregisteredEvent implements M.ServiceUnregisteredEvent {
final DateTime timestamp;
final String service;
final String method;
ServiceUnregisteredEvent(this.timestamp, this.service, this.method) {
assert(timestamp != null);
assert(service != null);
assert(method != null);
}
}
M.Event createEventFromServiceEvent(S.ServiceEvent event) {
switch (event.kind) {
case S.ServiceEvent.kVMUpdate:
return new VMUpdateEvent(event.timestamp, event.vm);
case S.ServiceEvent.kIsolateStart:
return new IsolateStartEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kIsolateRunnable:
return new IsolateRunnableEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kIsolateUpdate:
return new IsolateUpdateEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kIsolateReload:
return new IsolateReloadEvent(
event.timestamp, event.isolate, event.error);
case S.ServiceEvent.kIsolateExit:
return new IsolateExitEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kBreakpointAdded:
return new BreakpointAddedEvent(
event.timestamp, event.isolate, event.breakpoint);
case S.ServiceEvent.kBreakpointResolved:
return new BreakpointResolvedEvent(
event.timestamp, event.isolate, event.breakpoint);
case S.ServiceEvent.kBreakpointRemoved:
return new BreakpointRemovedEvent(
event.timestamp, event.isolate, event.breakpoint);
case S.ServiceEvent.kDebuggerSettingsUpdate:
return new DebuggerSettingsUpdateEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kResume:
return new ResumeEvent(event.timestamp, event.isolate, event.topFrame);
case S.ServiceEvent.kPauseStart:
return new PauseStartEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kPauseExit:
return new PauseExitEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kPausePostRequest:
return new PausePostRequestEvent(event.timestamp, event.isolate,
event.topFrame, event.atAsyncSuspension);
case S.ServiceEvent.kPauseBreakpoint:
return new PauseBreakpointEvent(
event.timestamp,
event.isolate,
event.pauseBreakpoints,
event.topFrame,
event.atAsyncSuspension,
event.breakpoint);
case S.Isolate.kLoggingStream:
return new LoggingEvent(event.timestamp, event.isolate, event.logRecord);
case S.ServiceEvent.kPauseInterrupted:
return new PauseInterruptedEvent(event.timestamp, event.isolate,
event.topFrame, event.atAsyncSuspension);
case S.ServiceEvent.kPauseException:
return new PauseExceptionEvent(
event.timestamp, event.isolate, event.topFrame, event.exception);
case S.ServiceEvent.kInspect:
return new InspectEvent(event.timestamp, event.isolate, event.inspectee);
case S.ServiceEvent.kGC:
return new GCEvent(event.timestamp, event.isolate);
case S.ServiceEvent.kServiceRegistered:
return new ServiceRegisteredEvent(
event.timestamp, event.service, event.method, event.alias);
case S.ServiceEvent.kServiceUnregistered:
return new ServiceUnregisteredEvent(
event.timestamp, event.service, event.method);
case S.ServiceEvent.kNone:
return new NoneEvent(event.timestamp, event.isolate);
default:
// Ignore unrecognized events.
Logger.root.severe('Unrecognized event: $event');
return null;
}
}

View file

@ -1,96 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library models;
import 'dart:async';
import 'package:observatory_2/object_graph.dart';
part 'src/models/exceptions.dart';
part 'src/models/objects/allocation_profile.dart';
part 'src/models/objects/breakpoint.dart';
part 'src/models/objects/class.dart';
part 'src/models/objects/code.dart';
part 'src/models/objects/context.dart';
part 'src/models/objects/error.dart';
part 'src/models/objects/event.dart';
part 'src/models/objects/extension_data.dart';
part 'src/models/objects/field.dart';
part 'src/models/objects/flag.dart';
part 'src/models/objects/frame.dart';
part 'src/models/objects/function.dart';
part 'src/models/objects/guarded.dart';
part 'src/models/objects/heap_space.dart';
part 'src/models/objects/icdata.dart';
part 'src/models/objects/inbound_references.dart';
part 'src/models/objects/instance.dart';
part 'src/models/objects/isolate.dart';
part 'src/models/objects/isolate_group.dart';
part 'src/models/objects/library.dart';
part 'src/models/objects/local_var_descriptors.dart';
part 'src/models/objects/map_association.dart';
part 'src/models/objects/megamorphiccache.dart';
part 'src/models/objects/metric.dart';
part 'src/models/objects/notification.dart';
part 'src/models/objects/object.dart';
part 'src/models/objects/objectpool.dart';
part 'src/models/objects/objectstore.dart';
part 'src/models/objects/pc_descriptors.dart';
part 'src/models/objects/persistent_handles.dart';
part 'src/models/objects/ports.dart';
part 'src/models/objects/retaining_path.dart';
part 'src/models/objects/sample_profile.dart';
part 'src/models/objects/script.dart';
part 'src/models/objects/sentinel.dart';
part 'src/models/objects/service.dart';
part 'src/models/objects/single_target_cache.dart';
part 'src/models/objects/source_location.dart';
part 'src/models/objects/subtype_test_cache.dart';
part 'src/models/objects/target.dart';
part 'src/models/objects/timeline.dart';
part 'src/models/objects/timeline_event.dart';
part 'src/models/objects/type_arguments.dart';
part 'src/models/objects/unknown.dart';
part 'src/models/objects/unlinked_call.dart';
part 'src/models/objects/vm.dart';
part 'src/models/repositories/allocation_profile.dart';
part 'src/models/repositories/breakpoint.dart';
part 'src/models/repositories/class.dart';
part 'src/models/repositories/context.dart';
part 'src/models/repositories/editor.dart';
part 'src/models/repositories/eval.dart';
part 'src/models/repositories/event.dart';
part 'src/models/repositories/field.dart';
part 'src/models/repositories/flag.dart';
part 'src/models/repositories/function.dart';
part 'src/models/repositories/heap_snapshot.dart';
part 'src/models/repositories/icdata.dart';
part 'src/models/repositories/inbound_references.dart';
part 'src/models/repositories/instance.dart';
part 'src/models/repositories/isolate.dart';
part 'src/models/repositories/isolate_group.dart';
part 'src/models/repositories/library.dart';
part 'src/models/repositories/megamorphiccache.dart';
part 'src/models/repositories/metric.dart';
part 'src/models/repositories/notification.dart';
part 'src/models/repositories/object.dart';
part 'src/models/repositories/objectpool.dart';
part 'src/models/repositories/objectstore.dart';
part 'src/models/repositories/persistent_handles.dart';
part 'src/models/repositories/ports.dart';
part 'src/models/repositories/reachable_size.dart';
part 'src/models/repositories/retained_size.dart';
part 'src/models/repositories/retaining_path.dart';
part 'src/models/repositories/sample_profile.dart';
part 'src/models/repositories/script.dart';
part 'src/models/repositories/single_target_cache.dart';
part 'src/models/repositories/strongly_reachable_instances.dart';
part 'src/models/repositories/subtype_test_cache.dart';
part 'src/models/repositories/target.dart';
part 'src/models/repositories/timeline.dart';
part 'src/models/repositories/type_arguments.dart';
part 'src/models/repositories/unlinked_call.dart';
part 'src/models/repositories/vm.dart';

File diff suppressed because it is too large Load diff

View file

@ -1,56 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library repositories;
import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'package:observatory_2/allocation_profile.dart';
import 'package:observatory_2/sample_profile.dart';
import 'package:observatory_2/object_graph.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart' as S;
import 'package:observatory_2/service_common.dart' as SC;
import 'package:observatory_2/src/repositories/timeline_base.dart';
part 'src/repositories/allocation_profile.dart';
part 'src/repositories/breakpoint.dart';
part 'src/repositories/class.dart';
part 'src/repositories/context.dart';
part 'src/repositories/editor.dart';
part 'src/repositories/eval.dart';
part 'src/repositories/event.dart';
part 'src/repositories/field.dart';
part 'src/repositories/flag.dart';
part 'src/repositories/function.dart';
part 'src/repositories/heap_snapshot.dart';
part 'src/repositories/icdata.dart';
part 'src/repositories/inbound_references.dart';
part 'src/repositories/instance.dart';
part 'src/repositories/isolate.dart';
part 'src/repositories/isolate_group.dart';
part 'src/repositories/library.dart';
part 'src/repositories/megamorphiccache.dart';
part 'src/repositories/metric.dart';
part 'src/repositories/notification.dart';
part 'src/repositories/object.dart';
part 'src/repositories/objectpool.dart';
part 'src/repositories/objectstore.dart';
part 'src/repositories/persistent_handles.dart';
part 'src/repositories/ports.dart';
part 'src/repositories/reachable_size.dart';
part 'src/repositories/retained_size.dart';
part 'src/repositories/retaining_path.dart';
part 'src/repositories/sample_profile.dart';
part 'src/repositories/script.dart';
part 'src/repositories/settings.dart';
part 'src/repositories/single_target_cache.dart';
part 'src/repositories/strongly_reachable_instances.dart';
part 'src/repositories/subtype_test_cache.dart';
part 'src/repositories/target.dart';
part 'src/repositories/timeline.dart';
part 'src/repositories/type_arguments.dart';
part 'src/repositories/unlinked_call.dart';
part 'src/repositories/vm.dart';

View file

@ -1,13 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library sample_profiler;
import 'dart:async';
import 'package:logging/logging.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart';
import 'package:observatory_2/utils.dart';
part 'src/sample_profile/sample_profile.dart';

View file

@ -1,20 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library service;
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:math' as math;
import 'package:logging/logging.dart';
import 'package:observatory_2/event.dart' show createEventFromServiceEvent;
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/object_graph.dart';
import 'package:observatory_2/sample_profile.dart';
import 'package:observatory_2/service_common.dart';
import 'package:observatory_2/tracer.dart';
part 'src/service/object.dart';

View file

@ -1,343 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library service_common;
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:logging/logging.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart';
// Export the service library.
export 'package:observatory_2/service.dart';
/// Description of a VM target.
class WebSocketVMTarget implements M.Target {
// Last time this VM has been connected to.
int lastConnectionTime = 0;
bool get hasEverConnected => lastConnectionTime > 0;
// Chrome VM or standalone;
bool chrome = false;
bool get standalone => !chrome;
// User defined name.
String name;
// Network address of VM.
String networkAddress;
WebSocketVMTarget(this.networkAddress) {
name = networkAddress;
}
WebSocketVMTarget.fromMap(Map json) {
lastConnectionTime = json['lastConnectionTime'];
chrome = json['chrome'];
name = json['name'];
networkAddress = json['networkAddress'];
if (name == null) {
name = networkAddress;
}
}
Map toJson() {
return {
'lastConnectionTime': lastConnectionTime,
'chrome': chrome,
'name': name,
'networkAddress': networkAddress,
};
}
}
class _WebSocketRequest {
final String method;
final Map params;
final Completer<Map> completer;
_WebSocketRequest(this.method, this.params)
: completer = new Completer<Map>();
}
/// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html].
abstract class CommonWebSocket {
Future<void> connect(WebSocketVMTarget target, void onOpen(),
void onMessage(dynamic data), void onError(), void onClose());
bool get isOpen;
void send(dynamic data);
void close();
Future<ByteData> nonStringToByteData(dynamic data);
}
/// A [CommonWebSocketVM] communicates with a Dart VM over a CommonWebSocket.
/// The Dart VM can be embedded in Chromium or standalone.
abstract class CommonWebSocketVM extends VM {
final Completer _connected = new Completer();
final Completer<String> _disconnected = new Completer<String>();
final WebSocketVMTarget target;
final Map<String, _WebSocketRequest> _delayedRequests =
new Map<String, _WebSocketRequest>();
final Map<String, _WebSocketRequest> _pendingRequests =
new Map<String, _WebSocketRequest>();
int _requestSerial = 0;
bool _hasInitiatedConnect = false;
Utf8Decoder _utf8Decoder = const Utf8Decoder();
String get displayName => '${name}@${target.name}';
CommonWebSocket _webSocket;
CommonWebSocketVM(this.target, this._webSocket) {
assert(target != null);
}
void _notifyConnect() {
if (!_connected.isCompleted) {
Logger.root
.info('WebSocketVM connection opened: ${target.networkAddress}');
_connected.complete(this);
}
}
Future get onConnect => _connected.future;
bool get wasOrIsConnected => _connected.isCompleted;
bool get isConnected => wasOrIsConnected && !isDisconnected;
void _notifyDisconnect(String reason) {
if (!_disconnected.isCompleted) {
Logger.root
.info('WebSocketVM connection error: ${target.networkAddress}');
_disconnected.complete(reason);
}
}
Future<String> get onDisconnect => _disconnected.future;
bool get isDisconnected => _disconnected.isCompleted;
void disconnect({String reason = 'WebSocket closed'}) {
if (_hasInitiatedConnect) {
if (_webSocket != null) {
_webSocket.close();
}
}
// We don't need to cancel requests and notify here. These
// functions will be called again when the onClose callback
// fires. However, we may have a better 'reason' string now, so
// let's take care of business.
_cancelAllRequests(reason);
_notifyDisconnect(reason);
}
Future<Map> invokeRpcRaw(String method, Map params) async {
if (!_hasInitiatedConnect) {
_hasInitiatedConnect = true;
try {
await _webSocket.connect(
target, _onOpen, _onMessage, _onError, _onClose);
} catch (_, stack) {
_webSocket = null;
var exception = new NetworkRpcException('WebSocket closed');
return new Future.error(exception, stack);
}
}
if (_disconnected.isCompleted) {
// This connection was closed already.
var exception = new NetworkRpcException(await onDisconnect);
return new Future.error(exception);
}
String serial = (_requestSerial++).toString();
var request = new _WebSocketRequest(method, <String, dynamic>{
...params,
// Include internal response data.
'_includePrivateMembers': true,
});
if ((_webSocket != null) && _webSocket.isOpen) {
// Already connected, send request immediately.
_sendRequest(serial, request);
} else {
// Not connected yet, add to delayed requests.
_delayedRequests[serial] = request;
}
return request.completer.future;
}
void _onClose() {
_cancelAllRequests('WebSocket closed');
_notifyDisconnect('WebSocket closed');
}
// WebSocket error event handler.
void _onError() {
// TODO(turnidge): The implementors of CommonWebSocket have more
// error information available. Consider providing that here.
_cancelAllRequests('WebSocket closed due to error');
_notifyDisconnect('WebSocket closed due to error');
}
// WebSocket open event handler.
void _onOpen() {
target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch;
_sendAllDelayedRequests();
_notifyConnect();
}
Map _parseJSON(String message) {
var map;
try {
map = json.decode(message);
} catch (e, st) {
Logger.root.severe('Disconnecting: Error decoding message: $e\n$st');
disconnect(reason: 'Connection saw corrupt JSON message: $e');
return null;
}
if (map == null) {
Logger.root.severe("Disconnecting: Unable to decode 'null' message");
disconnect(reason: "Connection saw 'null' message");
return null;
}
return map;
}
void _onBinaryMessage(dynamic data) {
_webSocket.nonStringToByteData(data).then((ByteData bytes) {
var metadataOffset = 4;
var dataOffset = bytes.getUint32(0, Endian.little);
var metadataLength = dataOffset - metadataOffset;
var dataLength = bytes.lengthInBytes - dataOffset;
var metadata = _utf8Decoder.convert(new Uint8List.view(
bytes.buffer, bytes.offsetInBytes + metadataOffset, metadataLength));
var data = new Uint8List.view(
bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
var map = _parseJSON(metadata);
if (map == null || map['method'] != 'streamNotify') {
return;
}
var event = map['params']['event'];
var streamId = map['params']['streamId'];
scheduleMicrotask(() {
postServiceEvent(streamId, event, data);
});
});
}
void _onStringMessage(String data) {
var map = _parseJSON(data);
if (map == null) {
return;
}
if (map['method'] == 'streamNotify') {
var event = map['params']['event'];
var streamId = map['params']['streamId'];
scheduleMicrotask(() {
postServiceEvent(streamId, event, null);
});
return;
}
// Extract serial and result.
var serial = map['id'];
// Complete request.
var request = _pendingRequests.remove(serial);
if (request == null) {
Logger.root.severe('Received unexpected message: ${map}');
return;
}
if (request.method != 'getTagProfile' &&
request.method != 'getIsolateMetric' &&
request.method != 'getVMMetric') {
Logger.root.info('RESPONSE [${serial}] ${request.method}');
}
var result = map['result'];
if (result != null) {
request.completer.complete(result);
} else {
var exception = new ServerRpcException.fromMap(map['error']);
request.completer.completeError(exception);
}
}
// WebSocket message event handler.
void _onMessage(dynamic data) {
if (data is! String) {
_onBinaryMessage(data);
} else {
_onStringMessage(data);
}
}
void _cancelRequests(
Map<String, _WebSocketRequest> requests, String message) {
requests.forEach((String serial, _WebSocketRequest request) {
var exception = new NetworkRpcException(message +
'(id: $serial method: ${request.method} params: ${request.params})');
request.completer.completeError(exception);
});
requests.clear();
}
/// Cancel all pending and delayed requests by completing them with an error.
void _cancelAllRequests(String reason) {
String message = 'Canceling request: $reason';
if (_pendingRequests.length > 0) {
Logger.root.info('Canceling all pending requests.');
_cancelRequests(_pendingRequests, message);
}
if (_delayedRequests.length > 0) {
Logger.root.info('Canceling all delayed requests.');
_cancelRequests(_delayedRequests, message);
}
}
/// Send all delayed requests.
void _sendAllDelayedRequests() {
assert(_webSocket.isOpen);
if (_delayedRequests.length == 0) {
return;
}
Logger.root.info('Sending all delayed requests.');
// Send all delayed requests.
_delayedRequests.forEach(_sendRequest);
// Clear all delayed requests.
_delayedRequests.clear();
}
/// Send the request over WebSocket.
void _sendRequest(String serial, _WebSocketRequest request) {
assert(_webSocket.isOpen);
// Mark request as pending.
assert(_pendingRequests.containsKey(serial) == false);
_pendingRequests[serial] = request;
var message;
// Encode message.
if (target.chrome) {
message = json.encode({
'id': int.parse(serial),
'method': 'Dart.observatoryQuery',
'params': {'id': serial, 'query': request.method}
});
} else {
message = json.encode({
'jsonrpc': '2.0',
'id': serial,
'method': request.method,
'params': request.params
});
}
if (request.method != 'getTagProfile' &&
request.method != 'getIsolateMetric' &&
request.method != 'getVMMetric') {
Logger.root.info(
'GET [${serial}] ${request.method}(${request.params}) from ${target.networkAddress}');
}
// Send message.
_webSocket.send(message);
}
String toString() => displayName;
}

View file

@ -1,78 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library service_html;
import 'dart:async';
import 'dart:html';
import 'dart:typed_data';
import 'package:observatory_2/service_common.dart';
// Export the service library.
export 'package:observatory_2/service_common.dart';
class _HtmlWebSocket implements CommonWebSocket {
WebSocket _webSocket;
Future<void> connect(WebSocketVMTarget target, void onOpen(),
void onMessage(dynamic data), void onError(), void onClose()) async {
// The VM service will attempt to redirect our websocket connection request
// to DDS, but the dart:html WebSocket doesn't follow redirects. Instead of
// relying on a redirect, we'll request the websocket URI from the service.
// TODO(bkonyi): re-enable when DDS is enabled. Currently causing Observatory
// failures when running with Flutter (see
// https://github.com/flutter/flutter/issues/64333)
/*Uri getWebSocketUriRequest = Uri.parse(target.networkAddress);
getWebSocketUriRequest =
getWebSocketUriRequest.replace(scheme: 'http', pathSegments: [
...getWebSocketUriRequest.pathSegments.where((e) => e != 'ws'),
'getWebSocketTarget',
]);
final response = json.decode(await HttpRequest.getString(
getWebSocketUriRequest.toString(),
));
if (!response.containsKey('result') ||
!response['result'].containsKey('uri')) {
onError();
return;
}
target.networkAddress = response['result']['uri'];
*/
_webSocket = new WebSocket(target.networkAddress);
_webSocket.onClose.listen((CloseEvent) => onClose());
_webSocket.onError.listen((Event) => onError());
_webSocket.onOpen.listen((Event) => onOpen());
_webSocket.onMessage.listen((MessageEvent event) => onMessage(event.data));
}
bool get isOpen => _webSocket.readyState == WebSocket.OPEN;
void send(dynamic data) {
_webSocket.send(data);
}
void close() {
_webSocket.close();
}
Future<ByteData> nonStringToByteData(dynamic data) {
assert(data is Blob);
FileReader fileReader = new FileReader();
fileReader.readAsArrayBuffer(data);
return fileReader.onLoadEnd.first.then((e) {
Uint8List result = fileReader.result as Uint8List;
return new ByteData.view(
result.buffer, result.offsetInBytes, result.length);
});
}
}
/// The [WebSocketVM] communicates with a Dart VM over WebSocket. The Dart VM
/// can be embedded in Chromium or standalone. In the case of Chromium, we
/// make the service requests via the Chrome Remote Debugging Protocol.
class WebSocketVM extends CommonWebSocketVM {
WebSocketVM(WebSocketVMTarget target) : super(target, new _HtmlWebSocket());
}

View file

@ -1,58 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library service_io;
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:logging/logging.dart';
import 'package:observatory_2/service_common.dart';
// Export the service library.
export 'package:observatory_2/service_common.dart';
class _IOWebSocket implements CommonWebSocket {
WebSocket _webSocket;
Future<void> connect(WebSocketVMTarget target, void onOpen(),
void onMessage(dynamic data), void onError(), void onClose()) async {
try {
_webSocket = await WebSocket.connect(target.networkAddress);
_webSocket.listen(onMessage,
onError: (dynamic) => onError(),
onDone: onClose,
cancelOnError: true);
onOpen();
} catch (_) {
onError();
}
}
bool get isOpen =>
(_webSocket != null) && (_webSocket.readyState == WebSocket.open);
void send(dynamic data) {
_webSocket.add(data);
}
void close() {
if (_webSocket != null) {
_webSocket.close();
}
}
Future<ByteData> nonStringToByteData(dynamic data) {
assert(data is Uint8List);
Logger.root.info('Binary data size in bytes: ${data.lengthInBytes}');
return new Future.sync(() =>
new ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes));
}
}
/// The [WebSocketVM] communicates with a Dart VM over WebSocket.
class WebSocketVM extends CommonWebSocketVM {
WebSocketVM(WebSocketVMTarget target) : super(target, new _IOWebSocket());
}

View file

@ -1,90 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of allocation_profiler;
class AllocationProfile implements M.AllocationProfile {
static const _lastServiceGC = 'dateLastServiceGC';
final DateTime lastServiceGC;
static const _lastAccumulatorReset = 'dateLastAccumulatorReset';
final DateTime lastAccumulatorReset;
final S.HeapSpace newSpace;
final S.HeapSpace oldSpace;
final S.HeapSpace totalSpace;
final Iterable<M.ClassHeapStats> members;
AllocationProfile(S.ServiceMap map, {Map/*<String, List<String>>*/ defaults})
: lastAccumulatorReset = _intString2DateTime(map[_lastAccumulatorReset]),
lastServiceGC = _intString2DateTime(map[_lastServiceGC]),
oldSpace = new S.HeapSpace()..update(map['_heaps']['old']),
newSpace = new S.HeapSpace()..update(map['_heaps']['new']),
totalSpace = new S.HeapSpace(),
members = _convertMembers(map['members'], defaults: defaults) {
totalSpace.add(oldSpace);
totalSpace.add(newSpace);
}
static DateTime _intString2DateTime(String milliseconds) {
if ((milliseconds == null) || milliseconds == '') {
return null;
}
return new DateTime.fromMillisecondsSinceEpoch(int.parse(milliseconds));
}
static ClassHeapStats _convertMember(/*S.ServiceMap*/ map) {
assert(map['type'] == 'ClassHeapStats');
return new ClassHeapStats(map);
}
static List<M.ClassHeapStats> _convertMembers(Iterable/*<S.ServiceMap>*/ raw,
{Map/*<String, List<String>>*/ defaults}) {
final List<M.ClassHeapStats> members =
raw.map<ClassHeapStats>(_convertMember).toList();
if (defaults == null) {
return members;
}
final Map<String, List<ClassHeapStats>> aliases =
new Map.fromIterable(defaults.keys, value: (_) => <ClassHeapStats>[]);
final Map<String, List<ClassHeapStats>> accumulators =
<String, List<ClassHeapStats>>{};
defaults.forEach((/*String*/ key, /*List<String>*/ values) {
final classes = aliases[key];
accumulators.addAll(new Map.fromIterable(values, value: (_) => classes));
});
final List<M.ClassHeapStats> result = <M.ClassHeapStats>[];
members.forEach((M.ClassHeapStats member) {
if (accumulators.containsKey(member.clazz.id)) {
accumulators[member.clazz.id].add(member);
} else {
result.add(member);
}
});
return result
..addAll(
aliases.keys.map((key) => new ClassesHeapStats(key, aliases[key])));
}
}
class ClassHeapStats implements M.ClassHeapStats {
final S.Class clazz;
final String displayName = null;
final S.Allocations newSpace;
final S.Allocations oldSpace;
ClassHeapStats(Map map)
: clazz = map['class'],
oldSpace = new S.Allocations()..update(map['_old']),
newSpace = new S.Allocations()..update(map['_new']);
}
class ClassesHeapStats implements M.ClassHeapStats {
final S.Class clazz = null;
final String displayName;
final S.Allocations newSpace;
final S.Allocations oldSpace;
ClassesHeapStats(this.displayName, Iterable<ClassHeapStats> classes)
: oldSpace = new S.Allocations()..combine(classes.map((m) => m.oldSpace)),
newSpace = new S.Allocations()..combine(classes.map((m) => m.newSpace));
}

View file

@ -1,294 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of app;
/// The observatory application. Instances of this are created and owned
/// by the observatory_application custom element.
class ObservatoryApplication {
static ObservatoryApplication app;
final RenderingQueue queue = new RenderingQueue();
final TargetRepository targets = new TargetRepository(isConnectedVMTarget);
final EventRepository events = new EventRepository();
final NotificationRepository notifications = new NotificationRepository();
final _pageRegistry = <Page>[];
LocationManager _locationManager;
LocationManager get locationManager => _locationManager;
Page currentPage;
bool _vmConnected = false;
VM _vm;
VM get vm => _vm;
static bool isConnectedVMTarget(M.Target target) {
if (app._vm is CommonWebSocketVM) {
if ((app._vm as CommonWebSocketVM).target == target) {
return app._vm.isConnected;
}
}
return false;
}
_switchVM(VM newVM) {
final VM oldVM = _vm;
Logger.root.info('_switchVM from:${oldVM} to:${newVM}');
if (oldVM == newVM) {
// Do nothing.
return;
}
if (oldVM != null) {
print('disconnecting from the old VM ${oldVM}--');
// Disconnect from current VM.
stopGCEventListener();
notifications.deleteAll();
oldVM.disconnect();
}
if (newVM != null) {
// Mark that we haven't connected yet.
_vmConnected = false;
// On connect:
newVM.onConnect.then((_) async {
// We connected.
_vmConnected = true;
notifications.deleteDisconnectEvents();
await newVM.load();
// TODO(cbernaschina) smart connection of streams in the events object.
newVM.listenEventStream(VM.kVMStream, _onEvent);
newVM.listenEventStream(VM.kIsolateStream, _onEvent);
newVM.listenEventStream(VM.kDebugStream, _onEvent);
newVM.listenEventStream(VM.kServiceStream, _onEvent);
});
// On disconnect:
newVM.onDisconnect.then((String reason) {
if (this.vm != newVM) {
// This disconnect event occurred *after* a new VM was installed.
return;
}
// Let anyone looking at the targets know that we have disconnected
// from one.
targets.emitDisconnectEvent();
if (!_vmConnected) {
// Connection error. Navigate back to the connect page.
Logger.root.info('Connection failed, navigating to VM connect page.');
// Clear the vm.
_vm = null;
app.locationManager.go(Uris.vmConnect());
} else {
// Disconnect. Stay at the current page and push an a connection
// closed event.
Logger.root.info('Lost an existing connection to a VM');
events.add(new ConnectionClosedEvent(new DateTime.now(), reason));
}
});
}
_vm = newVM;
}
StreamSubscription _gcSubscription;
StreamSubscription _loggingSubscription;
Future startGCEventListener() async {
if (_gcSubscription != null || _vm == null) {
return;
}
_gcSubscription = await _vm.listenEventStream(VM.kGCStream, _onEvent);
}
Future startLoggingEventListener() async {
if (_loggingSubscription != null || _vm == null) {
return;
}
_loggingSubscription =
await _vm.listenEventStream(Isolate.kLoggingStream, _onEvent);
}
Future stopGCEventListener() async {
if (_gcSubscription == null) {
return;
}
_gcSubscription.cancel();
_gcSubscription = null;
}
Future stopLoggingEventListener() async {
if (_loggingSubscription == null) {
return;
}
_loggingSubscription.cancel();
_loggingSubscription = null;
}
final ObservatoryApplicationElement rootElement;
ServiceObject lastErrorOrException;
void _initOnce() {
assert(app == null);
app = this;
_registerPages();
// Visit the current page.
locationManager._visit();
}
void _deletePauseEvents(e) {
notifications.deletePauseEvents(isolate: e.isolate);
}
void _addNotification(M.Event e) {
notifications.add(new EventNotification(e));
}
void _onEvent(ServiceEvent event) {
assert(event.kind != ServiceEvent.kNone);
M.Event e = createEventFromServiceEvent(event);
if (e != null) {
events.add(e);
}
}
void _registerPages() {
_pageRegistry.add(new VMPage(this));
_pageRegistry.add(new FlagsPage(this));
_pageRegistry.add(new NativeMemoryProfilerPage(this));
_pageRegistry.add(new InspectPage(this));
_pageRegistry.add(new ClassTreePage(this));
_pageRegistry.add(new DebuggerPage(this));
_pageRegistry.add(new ObjectStorePage(this));
_pageRegistry.add(new CpuProfilerPage(this));
_pageRegistry.add(new TableCpuProfilerPage(this));
_pageRegistry.add(new AllocationProfilerPage(this));
_pageRegistry.add(new HeapMapPage(this));
_pageRegistry.add(new HeapSnapshotPage(this));
_pageRegistry.add(new VMConnectPage(this));
_pageRegistry.add(new IsolateReconnectPage(this));
_pageRegistry.add(new ErrorViewPage(this));
_pageRegistry.add(new MetricsPage(this));
_pageRegistry.add(new PersistentHandlesPage(this));
_pageRegistry.add(new PortsPage(this));
_pageRegistry.add(new LoggingPage(this));
_pageRegistry.add(new TimelinePage(this));
_pageRegistry.add(new TimelineDashboardPage(this));
_pageRegistry.add(new ProcessSnapshotPage(this));
// Note that ErrorPage must be the last entry in the list as it is
// the catch all.
_pageRegistry.add(new ErrorPage(this));
}
void _visit(Uri uri, Map internalArguments) {
if (internalArguments['trace'] != null) {
var traceArg = internalArguments['trace'];
if (traceArg == 'on') {
Tracer.start();
} else if (traceArg == 'off') {
Tracer.stop();
}
}
if (Tracer.current != null) {
Tracer.current.reset();
}
for (var i = 0; i < _pageRegistry.length; i++) {
var page = _pageRegistry[i];
if (page.canVisit(uri)) {
_installPage(page);
page.visit(uri, internalArguments);
return;
}
}
throw new ArgumentError.value(uri, 'uri');
}
/// Set the Observatory application page.
void _installPage(Page page) {
assert(page != null);
if (currentPage == page) {
// Already installed.
return;
}
if (currentPage != null) {
Logger.root.info('Uninstalling page: $currentPage');
currentPage.onUninstall();
// Clear children.
rootElement.children.clear();
}
Logger.root.info('Installing page: $page');
try {
page.onInstall();
} catch (e) {
Logger.root.severe('Failed to install page: $e');
}
// Add new page.
rootElement.children.add(page.element);
// Remember page.
currentPage = page;
}
ObservatoryApplication(this.rootElement) {
_locationManager = new LocationManager(this);
targets.onChange.listen((TargetChangeEvent e) {
if (e.disconnected) {
// We don't care about disconnected events.
return;
}
if (targets.current == null) {
_switchVM(null);
} else {
final bool currentTarget =
(_vm as WebSocketVM)?.target == targets.current;
final bool currentTargetConnected = (_vm != null) && _vm.isConnected;
if (!currentTarget || !currentTargetConnected) {
_switchVM(new WebSocketVM(targets.current));
_vm.onConnect.then((_) {
app.locationManager.go(Uris.vm());
});
_vm.load();
} else if (currentTargetConnected) {
app.locationManager.go(Uris.vm());
}
}
});
Logger.root.info('Setting initial target to ${targets.current.name}');
_switchVM(new WebSocketVM(targets.current));
_initOnce();
// delete pause events.
events.onIsolateExit.listen(_deletePauseEvents);
events.onResume.listen(_deletePauseEvents);
events.onPauseStart.listen(_deletePauseEvents);
events.onPauseExit.listen(_deletePauseEvents);
events.onPauseBreakpoint.listen(_deletePauseEvents);
events.onPauseInterrupted.listen(_deletePauseEvents);
events.onPauseException.listen(_deletePauseEvents);
// show notification for an event.
events.onIsolateReload.listen(_addNotification);
events.onPauseExit.listen(_addNotification);
events.onPauseBreakpoint.listen(_addNotification);
events.onPauseInterrupted.listen(_addNotification);
events.onPauseException.listen(_addNotification);
events.onInspect.listen(_addNotification);
events.onConnectionClosed.listen(_addNotification);
}
void handleException(e, st) {
if (e is ServerRpcException) {
if (e.code == ServerRpcException.kFeatureDisabled) return;
if (e.code == ServerRpcException.kIsolateMustBePaused) return;
if (e.code == ServerRpcException.kCannotAddBreakpoint) return;
Logger.root.fine('Dropping exception: ${e}\n${st}');
}
// TODO(turnidge): Report this failure via analytics.
Logger.root.warning('Caught exception: ${e}\n${st}');
notifications.add(new ExceptionNotification(e, stacktrace: st));
}
// This map keeps track of which curly-blocks have been expanded by the user.
Map<String, bool> expansions = {};
}

View file

@ -1,167 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of app;
class LocationManager {
final ObservatoryApplication _app;
/// [internalArguments] are parameters specified after a '---' in the
/// application URL.
final Map<String, String> internalArguments = new Map<String, String>();
Uri _uri;
/// [uri] is the application uri. Application uris consist of a path and
/// the queryParameters map.
Uri get uri => _uri;
LocationManager(this._app) {
window.onPopState.listen(_onBrowserNavigation);
// Determine initial application path.
var applicationPath = '${window.location.hash}';
if ((window.location.hash == '') || (window.location.hash == '#')) {
// Observatory has loaded but no application path has been specified,
// use the default.
// By default we navigate to the VM page.
applicationPath = Uris.vm();
}
// Update current application path.
window.history
.replaceState(applicationPath, document.title, applicationPath);
_updateApplicationLocation(applicationPath);
}
bool getBoolParameter(String name, bool defaultValue) {
var value = uri.queryParameters[name];
if ("true" == value) return true;
if ("false" == value) return false;
return defaultValue;
}
/// Called whenever the browser changes the location bar (e.g. forward or
/// back button press).
void _onBrowserNavigation(PopStateEvent event) {
_updateApplicationLocation(window.location.hash);
_visit();
}
/// Given an application url, generate an href link.
String makeLink(String url) => '#$url';
/// Update the application location. After this function returns,
/// [uri] and [debugArguments] will be updated.
_updateApplicationLocation(String url) {
if (url == Uris.vmConnect()) {
// When we go to the vm-connect page, drop all notifications.
_app.notifications.deleteAll();
}
// Chop off leading '#'.
if (url.startsWith('#')) {
url = url.substring(1);
}
// Fall through handles '#/'
// Chop off leading '/'.
if (url.startsWith('/')) {
url = url.substring(1);
}
// Parse out debug arguments.
if (url.contains('---')) {
var chunks = url.split('---');
url = chunks[0];
if ((chunks.length > 1) && (chunks[1] != '')) {
internalArguments.clear();
try {
internalArguments.addAll(Uri.splitQueryString(chunks[1]));
} catch (e) {
Logger.root.warning('Could not parse debug arguments ${e}');
}
}
}
_uri = Uri.parse(url);
}
/// Add [url] to the browser history.
_addToBrowserHistory(String url) {
window.history.pushState(url, document.title, url);
}
/// Notify the current page that something has changed.
_visit() {
Chain.capture(() => _app._visit(_uri, internalArguments), onError: (e, st) {
if (e is IsolateNotFound) {
var newPath = ((_app.vm == null || _app.vm.isDisconnected)
? '/vm-connect'
: '/isolate-reconnect');
var parameters = <String, dynamic>{};
parameters.addAll(_uri.queryParameters);
parameters['originalUri'] = _uri.toString();
parameters['isolateId'] = parameters['isolateId'];
var generatedUri = new Uri(path: newPath, queryParameters: parameters);
go(makeLink(generatedUri.toString()), true);
return;
}
// Surface any uncaught exceptions.
_app.handleException(e, st);
});
}
/// Navigate to [url].
void go(String url, [bool addToBrowserHistory = true]) {
if (addToBrowserHistory) {
_addToBrowserHistory(url);
}
_updateApplicationLocation(url);
_visit();
}
/// Starting with the current uri path and queryParameters, update
/// queryParameters present in [updateParameters], then generate a new uri
/// and navigate to that.
goReplacingParameters(Map updatedParameters,
[bool addToBrowserHistory = true]) {
go(makeLinkReplacingParameters(updatedParameters), addToBrowserHistory);
}
makeLinkReplacingParameters(Map updatedParameters) {
var parameters = new Map.from(_uri.queryParameters);
updatedParameters.forEach((k, v) {
parameters[k] = v;
});
// Ensure path starts with a slash.
var path = uri.path.startsWith('/') ? uri.path : '/${uri.path}';
var generatedUri = new Uri(path: path, queryParameters: parameters);
return makeLink(generatedUri.toString());
}
goForwardingParameters(String newPath, [bool addToBrowserHistory = true]) {
go(makeLinkForwardingParameters(newPath), addToBrowserHistory);
}
makeLinkForwardingParameters(String newPath) {
var parameters = _uri.queryParameters;
var generatedUri = new Uri(path: newPath, queryParameters: parameters);
return makeLink(generatedUri.toString());
}
/// Utility event handler when clicking on application url link.
void onGoto(MouseEvent event) {
if ((event.button > 0) ||
event.metaKey ||
event.ctrlKey ||
event.shiftKey ||
event.altKey) {
// Mouse event is not a left-click OR
// mouse event is a left-click with a modifier key:
// let browser handle.
return;
}
event.preventDefault();
// 'currentTarget' is the dom element that would process the event.
// If we use 'target' we might get an <em> element or somesuch.
Element target = event.currentTarget;
go(target.attributes['href']);
}
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of app;
class ExceptionNotification implements M.ExceptionNotification {
final exception;
/// [optional]
final StackTrace stacktrace;
ExceptionNotification(this.exception, {this.stacktrace});
}
class EventNotification implements M.EventNotification {
final M.Event event;
EventNotification(this.event);
}

File diff suppressed because it is too large Load diff

View file

@ -1,45 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of app;
/// Static settings database.
class _Settings {
static Storage _storage = window.localStorage;
/// Associated [value] with [key]. [value] must be JSON encodable.
static void set(String key, dynamic value) {
_storage[key] = json.encode(value);
}
/// Get value associated with [key]. Return value will be a JSON encodable
/// object.
static dynamic get(String key) {
var value = _storage[key];
if (value == null) {
return null;
}
return json.decode(value);
}
}
/// A group of settings each prefixed with group name and a dot.
class SettingsGroup {
/// Group name
final String group;
SettingsGroup(this.group);
String _fullKey(String key) => '$group.$key';
void set(String key, dynamic value) {
var fullKey = _fullKey(key);
_Settings.set(fullKey, value);
}
dynamic get(String key) {
var fullKey = _fullKey(key);
return _Settings.get(fullKey);
}
}

View file

@ -1,104 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of app;
typedef String ValueFormatter(dynamic value);
class SortedTableColumn {
static String toStringFormatter(dynamic v) {
return v != null ? v.toString() : '<null>';
}
final String label;
final ValueFormatter formatter;
SortedTableColumn.withFormatter(this.label, this.formatter);
SortedTableColumn(this.label) : formatter = toStringFormatter;
}
class SortedTableRow {
final List values;
SortedTableRow(this.values);
}
class SortedTable {
final List<SortedTableColumn> columns;
final List<SortedTableRow> rows = <SortedTableRow>[];
final List<int> sortedRows = [];
SortedTable(this.columns);
int _sortColumnIndex = 0;
set sortColumnIndex(var index) {
assert(index >= 0);
assert(index < columns.length);
_sortColumnIndex = index;
}
int get sortColumnIndex => _sortColumnIndex;
bool _sortDescending = true;
bool get sortDescending => _sortDescending;
set sortDescending(var descending) {
_sortDescending = descending;
}
dynamic getSortKeyFor(int row, int col) {
return rows[row].values[col];
}
int _sortFuncDescending(int i, int j) {
var a = getSortKeyFor(i, _sortColumnIndex);
var b = getSortKeyFor(j, _sortColumnIndex);
return b.compareTo(a);
}
int _sortFuncAscending(int i, int j) {
var a = getSortKeyFor(i, _sortColumnIndex);
var b = getSortKeyFor(j, _sortColumnIndex);
return a.compareTo(b);
}
void sort() {
assert(_sortColumnIndex >= 0);
assert(_sortColumnIndex < columns.length);
if (_sortDescending) {
sortedRows.sort(_sortFuncDescending);
} else {
sortedRows.sort(_sortFuncAscending);
}
}
void clearRows() {
rows.clear();
sortedRows.clear();
}
void addRow(SortedTableRow row) {
sortedRows.add(rows.length);
rows.add(row);
}
String getFormattedValue(int row, int column) {
var value = getValue(row, column);
var formatter = columns[column].formatter;
return formatter(value);
}
String getColumnLabel(int column) {
assert(column >= 0);
assert(column < columns.length);
// TODO(johnmccutchan): Move expander display decisions into html once
// tables and templates are better supported.
const arrowUp = '\u25BC';
const arrowDown = '\u25B2';
if (column != _sortColumnIndex) {
return columns[column].label + '\u2003';
}
return columns[column].label + (_sortDescending ? arrowUp : arrowDown);
}
dynamic getValue(int row, int column) {
return rows[row].values[column];
}
}

View file

@ -1,280 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of cli;
// Splits a line into a list of string args. Each arg retains any
// trailing whitespace so that we can reconstruct the original command
// line from the pieces.
List<String> _splitLine(String line) {
line = line.trimLeft();
var args = <String>[];
int pos = 0;
while (pos < line.length) {
int startPos = pos;
// Advance to end of word.
for (; pos < line.length && line[pos] != ' '; pos++);
// Advance to end of spaces.
for (; pos < line.length && line[pos] == ' '; pos++);
args.add(line.substring(startPos, pos));
}
return args;
}
// Concatenates the first 'count' args.
String _concatArgs(List<String> args, int count) {
if (count == 0) {
return '';
}
return '${args.sublist(0, count).join('')}';
}
// Shared functionality for RootCommand and Command.
abstract class _CommandBase {
_CommandBase(List<Command> children) {
assert(children != null);
_children.addAll(children);
for (var child in _children) {
child._parent = this;
}
}
// A command may optionally have sub-commands.
List<Command> _children = <Command>[];
_CommandBase _parent;
int get _depth => (_parent == null ? 0 : _parent._depth + 1);
// Override in subclasses to provide command-specific argument completion.
//
// Given a list of arguments to this command, provide a list of
// possible completions for those arguments.
Future<List<String>> complete(List<String> args) =>
new Future.value(<String>[]);
// Override in subclasses to provide command-specific execution.
Future run(List<String> args);
// Returns a list of local subcommands which match the args.
List<Command> _matchLocal(String argWithSpace, bool preferExact) {
var matches = <Command>[];
var arg = argWithSpace.trimRight();
for (var child in _children) {
if (child.name.startsWith(arg)) {
if (preferExact && ((child.name == arg) || (child.alias == arg))) {
return [child];
}
matches.add(child);
}
}
return matches;
}
// Returns the set of commands could be triggered by a list of
// arguments.
List<Command> _match(List<String> args, bool preferExact) {
if (args.isEmpty) {
return <Command>[];
}
bool lastArg = (args.length == 1);
var matches = _matchLocal(args[0], !lastArg || preferExact);
if (matches.isEmpty) {
return <Command>[];
} else if (matches.length == 1) {
var childMatches = matches[0]._match(args.sublist(1), preferExact);
if (childMatches.isEmpty) {
return matches;
} else {
return childMatches;
}
} else {
return matches;
}
}
// Builds a list of completions for this command.
Future<List<String>> _buildCompletions(
List<String> args, bool addEmptyString) {
return complete(args.sublist(_depth, args.length)).then((completions) {
if (addEmptyString &&
completions.isEmpty &&
args[args.length - 1] == '') {
// Special case allowance for an empty particle at the end of
// the command.
completions = <String>[''];
}
var prefix = _concatArgs(args, _depth);
return completions.map((str) => '${prefix}${str}').toList();
});
}
}
// The root of a tree of commands.
class RootCommand extends _CommandBase {
RootCommand(List<Command> children, [List<String> history])
: this._(children, history ?? ['']);
RootCommand._(List<Command> children, List<String> history)
: history = history,
historyPos = history.length - 1,
super(children);
// Provides a list of possible completions for a line of text.
Future<List<String>> completeCommand(String line) {
var args = _splitLine(line);
bool showAll = line.endsWith(' ') || args.isEmpty;
if (showAll) {
// Adding an empty string to the end causes us to match all
// subcommands of the last command.
args.add('');
}
var commands = _match(args, false);
if (commands.isEmpty) {
// No matching commands.
return new Future.value(<String>[]);
}
int matchLen = commands[0]._depth;
if (matchLen < args.length) {
// We were able to find a command which matches a prefix of the
// args, but not the full list.
if (commands.length == 1) {
// The matching command is unique. Attempt to provide local
// argument completion from the command.
return commands[0]._buildCompletions(args, true);
} else {
// An ambiguous prefix match leaves us nowhere. The user is
// typing a bunch of stuff that we don't know how to complete.
return new Future.value(<String>[]);
}
}
// We have found a set of commands which match all of the args.
// Return the completion strings.
var prefix = _concatArgs(args, args.length - 1);
var completions =
commands.map((command) => '${prefix}${command.name} ').toList();
if (matchLen == args.length) {
// If we are showing all possibilities, also include local
// completions for the parent command.
return commands[0]
._parent
._buildCompletions(args, false)
.then((localCompletions) {
completions.addAll(localCompletions);
return completions;
});
}
return new Future.value(completions);
}
// Runs a command.
Future runCommand(String line) {
_historyAdvance(line);
var args = _splitLine(line);
var commands = _match(args, true);
if (commands.isEmpty) {
return new Future.error(new NoSuchCommandException(line));
} else if (commands.length == 1) {
return commands[0].run(args.sublist(commands[0]._depth));
} else {
return new Future.error(new AmbiguousCommandException(line, commands));
}
}
// Find all matching commands. Useful for implementing help systems.
List<Command> matchCommand(List<String> args, bool preferExact) {
if (args.isEmpty) {
// Adding an empty string to the end causes us to match all
// subcommands of the last command.
args.add('');
}
return _match(args, preferExact);
}
// Command line history always contains one slot to hold the current
// line, so we start off with one entry.
List<String> history;
int historyPos;
String historyPrev(String line) {
if (historyPos == 0) {
return line;
}
history[historyPos] = line;
historyPos--;
return history[historyPos];
}
String historyNext(String line) {
if (historyPos == history.length - 1) {
return line;
}
history[historyPos] = line;
historyPos++;
return history[historyPos];
}
void _historyAdvance(String line) {
// Replace the last history line.
historyPos = history.length - 1;
history[historyPos] = line;
// Create an empty spot for the next line.
history.add('');
historyPos++;
}
Future run(List<String> args) {
throw 'should-not-execute-the-root-command';
}
toString() => 'RootCommand';
}
// A node in the command tree.
abstract class Command extends _CommandBase {
Command(this.name, List<Command> children) : super(children);
final String name;
String alias;
String get fullName {
if (_parent is RootCommand) {
return name;
} else {
Command parent = _parent;
return '${parent.fullName} $name';
}
}
toString() => 'Command(${name})';
}
abstract class CommandException implements Exception {}
class AmbiguousCommandException extends CommandException {
AmbiguousCommandException(this.command, this.matches);
final String command;
final List<Command> matches;
@override
String toString() {
List<String> matchNames =
matches.map((Command command) => '${command.fullName}').toList();
return "Command '$command' is ambiguous: $matchNames";
}
}
class NoSuchCommandException extends CommandException {
NoSuchCommandException(this.command);
final String command;
@override
String toString() => "No such command: '$command'";
}

View file

@ -1,14 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of debugger;
// TODO(turnidge): Move more of ObservatoryDebugger to this class.
abstract class Debugger {
VM get vm;
Isolate get isolate;
M.ObjectRepository objects;
ServiceMap get stack;
int get currentFrame;
}

View file

@ -1,462 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of debugger;
class DebuggerLocation {
DebuggerLocation.file(this.script, this.line, this.col);
DebuggerLocation.func(this.function);
DebuggerLocation.error(this.errorMessage);
static RegExp sourceLocMatcher = new RegExp(r'^([^\d:][^:]+:)?(\d+)(:\d+)?');
static RegExp packageLocMatcher =
new RegExp(r'^package:([^\d:][^:]+:)?(\d+)(:\d+)?');
static RegExp functionMatcher = new RegExp(r'^([^.]+)([.][^.]+)?');
/// Parses a source location description.
///
/// Formats:
/// '' - current position
/// 13 - line 13, current script
/// 13:20 - line 13, col 20, current script
/// script.dart:13 - line 13, script.dart
/// script.dart:13:20 - line 13, col 20, script.dart
/// package:a/b.dart:13 - line 13, "b.dart" in package "a".
/// package:a/b.dart:13:20 - line 13, col 20, "b.dart" in package "a".
/// main - function
/// FormatException - constructor
/// _SHA1._updateHash - method
static Future<DebuggerLocation> parse(Debugger debugger, String locDesc) {
if (locDesc == '') {
// Special case: '' means return current location.
return _currentLocation(debugger);
}
// Parse the location description.
var match = sourceLocMatcher.firstMatch(locDesc);
if (match != null) {
return _parseScriptLine(debugger, match);
}
match = packageLocMatcher.firstMatch(locDesc);
if (match != null) {
return _parseScriptLine(debugger, match, package: true);
}
match = functionMatcher.firstMatch(locDesc);
if (match != null) {
return _parseFunction(debugger, match);
}
return new Future.value(
new DebuggerLocation.error("Invalid source location '${locDesc}'"));
}
static Future<Frame> _currentFrame(Debugger debugger) async {
ServiceMap stack = debugger.stack;
if (stack == null || stack['frames'].length == 0) {
return null;
}
return stack['frames'][debugger.currentFrame];
}
static Future<DebuggerLocation> _currentLocation(Debugger debugger) async {
var frame = await _currentFrame(debugger);
if (frame == null) {
return new DebuggerLocation.error(
'A script must be provided when the stack is empty');
}
Script script = frame.location.script;
await script.load();
var line = script.tokenToLine(frame.location.tokenPos);
var col = script.tokenToCol(frame.location.tokenPos);
return new DebuggerLocation.file(script, line, col);
}
static Future<DebuggerLocation> _parseScriptLine(
Debugger debugger, Match match,
{bool package = false}) async {
var scriptName = match.group(1);
if (package) {
scriptName = "package:$scriptName";
}
if (scriptName != null) {
scriptName = scriptName.substring(0, scriptName.length - 1);
}
var lineStr = match.group(2);
assert(lineStr != null);
var colStr = match.group(3);
if (colStr != null) {
colStr = colStr.substring(1);
}
var line = int.tryParse(lineStr) ?? -1;
var col = (colStr != null ? int.tryParse(colStr) ?? -1 : null);
if (line == -1) {
return new Future.value(
new DebuggerLocation.error("Line '${lineStr}' must be an integer"));
}
if (col == -1) {
return new Future.value(
new DebuggerLocation.error("Column '${colStr}' must be an integer"));
}
if (scriptName != null) {
// Resolve the script.
Set<Script> scripts = await _lookupScript(debugger.isolate, scriptName);
if (scripts.length == 0) {
scripts =
await _lookupScript(debugger.isolate, scriptName, useUri: true);
}
if (scripts.length == 0) {
return new DebuggerLocation.error("Script '${scriptName}' not found");
} else if (scripts.length == 1) {
return new DebuggerLocation.file(scripts.single, line, col);
} else {
// TODO(turnidge): Allow the user to disambiguate.
return new DebuggerLocation.error(
"Script '${scriptName}' is ambiguous");
}
} else {
// No script provided. Default to top of stack for now.
var frame = await _currentFrame(debugger);
if (frame == null) {
return new Future.value(new DebuggerLocation.error(
'A script must be provided when the stack is empty'));
}
Script script = frame.location.script;
await script.load();
return new DebuggerLocation.file(script, line, col);
}
}
static Future<Set<Script>> _lookupScript(Isolate isolate, String name,
{bool allowPrefix = false, bool useUri = false}) {
var pending = <Future>[];
for (var lib in isolate.libraries) {
if (!lib.loaded) {
pending.add(lib.load());
}
}
return Future.wait(pending).then((_) {
var matches = <Script>{};
for (var lib in isolate.libraries) {
for (var script in lib.scripts) {
final String haystack = useUri ? script.uri : script.name;
if (allowPrefix) {
if (haystack.startsWith(name)) {
matches.add(script);
}
} else {
if (name == haystack) {
matches.add(script);
}
}
}
}
return matches;
});
}
static List<ServiceFunction> _lookupFunction(Isolate isolate, String name,
{bool allowPrefix = false}) {
var matches = <ServiceFunction>[];
for (var lib in isolate.libraries) {
assert(lib.loaded);
for (var function in lib.functions) {
if (allowPrefix) {
if (function.name.startsWith(name)) {
matches.add(function);
}
} else {
if (name == function.name) {
matches.add(function);
}
}
}
}
return matches;
}
static Future<List<Class>> _lookupClass(Isolate isolate, String name,
{bool allowPrefix = false}) async {
if (isolate == null) {
return [];
}
var pending = <Future>[];
for (var lib in isolate.libraries) {
assert(lib.loaded);
for (var cls in lib.classes) {
if (!cls.loaded) {
pending.add(cls.load());
}
}
}
await Future.wait(pending);
var matches = <Class>[];
for (var lib in isolate.libraries) {
for (var cls in lib.classes) {
if (allowPrefix) {
if (cls.name.startsWith(name)) {
matches.add(cls);
}
} else {
if (name == cls.name) {
matches.add(cls);
}
}
}
}
return matches;
}
static ServiceFunction _getConstructor(Class cls, String name) {
for (var function in cls.functions) {
assert(cls.loaded);
if (name == function.name) {
return function;
}
}
return null;
}
// TODO(turnidge): This does not handle named functions which are
// inside of named functions, e.g. foo.bar.baz.
static Future<DebuggerLocation> _parseFunction(
Debugger debugger, Match match) {
Isolate isolate = debugger.isolate;
var base = match.group(1);
var qualifier = match.group(2);
assert(base != null);
return _lookupClass(isolate, base).then((classes) {
var functions = [];
if (qualifier == null) {
// Unqualified name is either a function or a constructor.
functions.addAll(_lookupFunction(isolate, base));
for (var cls in classes) {
// Look for a self-named constructor.
var constructor = _getConstructor(cls, cls.name);
if (constructor != null) {
functions.add(constructor);
}
}
} else {
// Qualified name.
var functionName = qualifier.substring(1);
for (var cls in classes) {
assert(cls.loaded);
for (var function in cls.functions) {
if (function.kind == M.FunctionKind.constructor) {
// Constructor names are class-qualified.
if (match.group(0) == function.name) {
functions.add(function);
}
} else {
if (functionName == function.name) {
functions.add(function);
}
}
}
}
}
if (functions.length == 0) {
return new DebuggerLocation.error(
"Function '${match.group(0)}' not found");
} else if (functions.length == 1) {
return new DebuggerLocation.func(functions[0]);
} else {
// TODO(turnidge): Allow the user to disambiguate.
return new DebuggerLocation.error(
"Function '${match.group(0)}' is ambiguous");
}
});
}
static RegExp partialSourceLocMatcher =
new RegExp(r'^([^\d:]?[^:]+[:]?)?(\d+)?([:]\d*)?');
static RegExp partialFunctionMatcher = new RegExp(r'^([^.]*)([.][^.]*)?');
/// Completes a partial source location description.
static Future<List<String>> complete(Debugger debugger, String locDesc) {
var pending = <Future<List<String>>>[];
var match = partialFunctionMatcher.firstMatch(locDesc);
if (match != null) {
pending.add(_completeFunction(debugger, match));
}
match = partialSourceLocMatcher.firstMatch(locDesc);
if (match != null) {
pending.add(_completeFile(debugger, match));
}
return Future.wait(pending).then((List<List<String>> responses) {
var completions = <String>[];
for (var response in responses) {
completions.addAll(response);
}
return completions;
});
}
static Future<List<String>> _completeFunction(
Debugger debugger, Match match) {
Isolate isolate = debugger.isolate;
var base = match.group(1);
var qualifier = match.group(2);
base = (base == null ? '' : base);
if (qualifier == null) {
return _lookupClass(isolate, base, allowPrefix: true).then((classes) {
var completions = <String>[];
// Complete top-level function names.
var functions = _lookupFunction(isolate, base, allowPrefix: true);
var funcNames = functions.map((f) => f.name).toList();
funcNames.sort();
completions.addAll(funcNames);
// Complete class names.
var classNames = classes.map((f) => f.name).toList();
classNames.sort();
completions.addAll(classNames);
return completions;
});
} else {
return _lookupClass(isolate, base, allowPrefix: false).then((classes) {
var completions = <String>[];
for (var cls in classes) {
for (var function in cls.functions) {
if (function.kind == M.FunctionKind.constructor) {
if (function.name.startsWith(match.group(0))) {
completions.add(function.name);
}
} else {
if (function.qualifiedName.startsWith(match.group(0))) {
completions.add(function.qualifiedName);
}
}
}
}
completions.sort();
return completions;
});
}
}
static bool _startsWithDigit(String s) {
return '0'.compareTo(s[0]) <= 0 && '9'.compareTo(s[0]) >= 0;
}
static Future<List<String>> _completeFile(
Debugger debugger, Match match) async {
var scriptName;
var scriptNameComplete = false;
var lineStr;
var lineStrComplete = false;
var colStr;
if (_startsWithDigit(match.group(1))) {
// CASE 1: We have matched a prefix of (lineStr:)(colStr)
var frame = await _currentFrame(debugger);
if (frame == null) {
return [];
}
scriptName = frame.location.script.name;
scriptNameComplete = true;
lineStr = match.group(1);
lineStr = (lineStr == null ? '' : lineStr);
if (lineStr.endsWith(':')) {
lineStr = lineStr.substring(0, lineStr.length - 1);
lineStrComplete = true;
}
colStr = match.group(2);
colStr = (colStr == null ? '' : colStr);
} else {
// CASE 2: We have matched a prefix of (scriptName:)(lineStr)(:colStr)
scriptName = match.group(1);
scriptName = (scriptName == null ? '' : scriptName);
if (scriptName.endsWith(':')) {
scriptName = scriptName.substring(0, scriptName.length - 1);
scriptNameComplete = true;
}
lineStr = match.group(2);
lineStr = (lineStr == null ? '' : lineStr);
colStr = match.group(3);
colStr = (colStr == null ? '' : colStr);
if (colStr.startsWith(':')) {
lineStrComplete = true;
colStr = colStr.substring(1);
}
}
if (!scriptNameComplete) {
// The script name is incomplete. Complete it.
var scripts =
await _lookupScript(debugger.isolate, scriptName, allowPrefix: true);
var completions = <String>[];
for (var script in scripts) {
completions.add(script.name + ':');
}
completions.sort();
return completions;
} else {
// The script name is complete. Look it up.
var scripts =
await _lookupScript(debugger.isolate, scriptName, allowPrefix: false);
if (scripts.isEmpty) {
return [];
}
var script = scripts.first;
await script.load();
if (!lineStrComplete) {
// Complete the line.
var sharedPrefix = '${script.name}:';
var completions = <String>[];
var report = await script.isolate
.getSourceReport([Isolate.kPossibleBreakpointsReport], script);
Set<int> possibleBpts = getPossibleBreakpointLines(report, script);
for (var line in possibleBpts) {
var currentLineStr = line.toString();
if (currentLineStr.startsWith(lineStr)) {
completions.add('${sharedPrefix}${currentLineStr} ');
completions.add('${sharedPrefix}${currentLineStr}:');
}
}
return completions;
} else {
// Complete the column.
int lineNum = int.parse(lineStr);
var scriptLine = script.getLine(lineNum);
var sharedPrefix = '${script.name}:${lineStr}:';
var completions = <String>[];
int maxCol = scriptLine.text.trimRight().runes.length;
for (int i = 1; i <= maxCol; i++) {
var currentColStr = i.toString();
if (currentColStr.startsWith(colStr)) {
completions.add('${sharedPrefix}${currentColStr} ');
}
}
return completions;
}
}
}
String toString() {
if (valid) {
if (function != null) {
return '${function.qualifiedName}';
} else if (col != null) {
return '${script.name}:${line}:${col}';
} else {
return '${script.name}:${line}';
}
}
return 'invalid source location (${errorMessage})';
}
Script script;
int line;
int col;
ServiceFunction function;
String errorMessage;
bool get valid => (errorMessage == null);
}

View file

@ -1,573 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/utils.dart';
enum _SortingField {
newInstances,
newInternalSize,
newExternalSize,
newSize,
oldInstances,
oldInternalSize,
oldExternalSize,
oldSize,
instances,
internalSize,
externalSize,
size,
className,
}
enum _SortingDirection { ascending, descending }
class AllocationProfileElement extends CustomElement implements Renderable {
RenderingScheduler<AllocationProfileElement> _r;
Stream<RenderedEvent<AllocationProfileElement>> get onRendered =>
_r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.AllocationProfileRepository _repository;
M.AllocationProfile _profile;
bool _autoRefresh = false;
bool _isCompacted = false;
StreamSubscription _gcSubscription;
_SortingField _sortingField = _SortingField.size;
_SortingDirection _sortingDirection = _SortingDirection.descending;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
factory AllocationProfileElement(
M.VM vm,
M.IsolateRef isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.AllocationProfileRepository repository,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(repository != null);
AllocationProfileElement e = new AllocationProfileElement.created();
e._r = new RenderingScheduler<AllocationProfileElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._repository = repository;
return e;
}
AllocationProfileElement.created() : super.created('allocation-profile');
@override
attached() {
super.attached();
_r.enable();
_refresh();
_gcSubscription = _events.onGCEvent.listen((e) {
if (_autoRefresh && (e.isolate.id == _isolate.id)) {
_refresh();
}
});
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_gcSubscription.cancel();
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('allocation profile'),
(new NavRefreshElement(
label: 'Download', disabled: _profile == null, queue: _r.queue)
..onRefresh.listen((_) => _downloadCSV()))
.element,
(new NavRefreshElement(label: 'GC', queue: _r.queue)
..onRefresh.listen((_) => _refresh(gc: true)))
.element,
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((_) => _refresh()))
.element,
new DivElement()
..classes = ['nav-option']
..children = <Element>[
new CheckboxInputElement()
..id = 'allocation-profile-auto-refresh'
..checked = _autoRefresh
..onChange.listen((_) => _autoRefresh = !_autoRefresh),
new LabelElement()
..htmlFor = 'allocation-profile-auto-refresh'
..text = 'Auto-refresh on GC'
],
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Allocation Profile',
new HRElement()
]
];
if (_profile == null) {
children.addAll([
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[new HeadingElement.h2()..text = 'Loading...']
]);
} else {
children.addAll([
new DivElement()
..classes = ['content-centered-big']
..children = _isCompacted
? []
: [
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'last forced GC at',
new DivElement()
..classes = ['memberValue']
..text = _profile.lastServiceGC == null
? '---'
: '${_profile.lastServiceGC}',
],
],
new HRElement(),
],
new DivElement()
..classes = ['content-centered-big', 'compactable']
..children = <Element>[
new DivElement()
..classes = ['heap-space', 'left']
..children = _isCompacted
? [
new HeadingElement.h2()
..text = 'New Generation '
'(${_usedCaption(_profile.newSpace)})',
]
: [
new HeadingElement.h2()..text = 'New Generation',
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createSpaceMembers(_profile.newSpace),
],
new DivElement()
..classes = ['heap-space', 'left']
..children = _isCompacted
? [
new HeadingElement.h2()
..text = 'Old Generation '
'(${_usedCaption(_profile.oldSpace)})',
]
: [
new HeadingElement.h2()..text = 'Old Generation',
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createSpaceMembers(_profile.oldSpace),
],
new DivElement()
..classes = ['heap-space', 'left']
..children = _isCompacted
? [
new HeadingElement.h2()
..text = 'Total '
'(${_usedCaption(_profile.totalSpace)})',
]
: [
new HeadingElement.h2()..text = 'Total',
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createSpaceMembers(_profile.totalSpace),
],
new ButtonElement()
..classes = ['compact']
..text = _isCompacted ? 'expand ▼' : 'compact ▲'
..onClick.listen((_) {
_isCompacted = !_isCompacted;
_r.dirty();
}),
new HRElement()
],
new DivElement()
..classes = _isCompacted ? ['collection', 'expanded'] : ['collection']
..children = <Element>[
new VirtualCollectionElement(
_createCollectionLine, _updateCollectionLine,
createHeader: _createCollectionHeader,
search: _search,
items: _profile.members.toList()..sort(_createSorter()),
queue: _r.queue)
.element
]
]);
}
}
_createSorter() {
var getter;
switch (_sortingField) {
case _SortingField.newInternalSize:
getter = _getNewInternalSize;
break;
case _SortingField.newExternalSize:
getter = _getNewExternalSize;
break;
case _SortingField.newSize:
getter = _getNewSize;
break;
case _SortingField.newInstances:
getter = _getNewInstances;
break;
case _SortingField.oldInternalSize:
getter = _getOldInternalSize;
break;
case _SortingField.oldExternalSize:
getter = _getOldExternalSize;
break;
case _SortingField.oldSize:
getter = _getOldSize;
break;
case _SortingField.oldInstances:
getter = _getOldInstances;
break;
case _SortingField.internalSize:
getter = _getInternalSize;
break;
case _SortingField.externalSize:
getter = _getExternalSize;
break;
case _SortingField.size:
getter = _getSize;
break;
case _SortingField.instances:
getter = _getInstances;
break;
case _SortingField.className:
getter = (M.ClassHeapStats s) => s.clazz.name;
break;
}
switch (_sortingDirection) {
case _SortingDirection.ascending:
int sort(M.ClassHeapStats a, M.ClassHeapStats b) {
return getter(a).compareTo(getter(b));
}
return sort;
case _SortingDirection.descending:
int sort(M.ClassHeapStats a, M.ClassHeapStats b) {
return getter(b).compareTo(getter(a));
}
return sort;
}
}
static HtmlElement _createCollectionLine() => new DivElement()
..classes = ['collection-item']
..children = <Element>[
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['instances']
..text = '0',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['instances']
..text = '0',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
new SpanElement()
..classes = ['instances']
..text = '0',
new SpanElement()..classes = ['name']
];
List<HtmlElement> _createCollectionHeader() => [
new DivElement()
..classes = ['collection-item']
..children = <Element>[
new SpanElement()
..classes = ['group']
..text = 'New Generation',
new SpanElement()
..classes = ['group']
..text = 'Old Generation',
new SpanElement()
..classes = ['group']
..text = 'Total',
new SpanElement()
..classes = ['group']
..text = '',
],
new DivElement()
..classes = ['collection-item']
..children = <Element>[
_createHeaderButton(const ['bytes'], 'Internal',
_SortingField.newInternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'External',
_SortingField.newExternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size', _SortingField.newSize,
_SortingDirection.descending),
_createHeaderButton(const ['instances'], 'Instances',
_SortingField.newInstances, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Internal',
_SortingField.oldInternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'External',
_SortingField.oldExternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size', _SortingField.oldSize,
_SortingDirection.descending),
_createHeaderButton(const ['instances'], 'Instances',
_SortingField.oldInstances, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Internal',
_SortingField.internalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'External',
_SortingField.externalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size', _SortingField.size,
_SortingDirection.descending),
_createHeaderButton(const ['instances'], 'Instances',
_SortingField.instances, _SortingDirection.descending),
_createHeaderButton(const ['name'], 'Class',
_SortingField.className, _SortingDirection.ascending)
],
];
ButtonElement _createHeaderButton(List<String> classes, String text,
_SortingField field, _SortingDirection direction) =>
new ButtonElement()
..classes = classes
..text = _sortingField != field
? text
: _sortingDirection == _SortingDirection.ascending
? '$text'
: '$text'
..onClick.listen((_) => _setSorting(field, direction));
void _setSorting(_SortingField field, _SortingDirection defaultDirection) {
if (_sortingField == field) {
switch (_sortingDirection) {
case _SortingDirection.descending:
_sortingDirection = _SortingDirection.ascending;
break;
case _SortingDirection.ascending:
_sortingDirection = _SortingDirection.descending;
break;
}
} else {
_sortingDirection = defaultDirection;
_sortingField = field;
}
_r.dirty();
}
void _updateCollectionLine(Element e, itemDynamic, index) {
M.ClassHeapStats item = itemDynamic;
e.children[0].text = Utils.formatSize(_getNewInternalSize(item));
e.children[1].text = Utils.formatSize(_getNewExternalSize(item));
e.children[2].text = Utils.formatSize(_getNewSize(item));
e.children[3].text = '${_getNewInstances(item)}';
e.children[4].text = Utils.formatSize(_getOldInternalSize(item));
e.children[5].text = Utils.formatSize(_getOldExternalSize(item));
e.children[6].text = Utils.formatSize(_getOldSize(item));
e.children[7].text = '${_getOldInstances(item)}';
e.children[8].text = Utils.formatSize(_getInternalSize(item));
e.children[9].text = Utils.formatSize(_getExternalSize(item));
e.children[10].text = Utils.formatSize(_getSize(item));
e.children[11].text = '${_getInstances(item)}';
e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
.element
..classes = ['name'];
}
bool _search(Pattern pattern, itemDynamic) {
M.ClassHeapStats item = itemDynamic;
return item.clazz.name.contains(pattern);
}
static String _usedCaption(M.HeapSpace space) =>
'${Utils.formatSize(space.used)}'
' of '
'${Utils.formatSize(space.capacity)}';
static List<Element> _createSpaceMembers(M.HeapSpace space) {
final used = _usedCaption(space);
final ext = '${Utils.formatSize(space.external)}';
final collections = '${space.collections}';
final avgCollectionTime =
'${Utils.formatDurationInMilliseconds(space.avgCollectionTime)} ms';
final totalCollectionTime =
'${Utils.formatDurationInSeconds(space.totalCollectionTime)} secs';
final avgCollectionPeriod =
'${Utils.formatDurationInMilliseconds(space.avgCollectionPeriod)} ms';
return [
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'used',
new DivElement()
..classes = ['memberValue']
..text = used
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'external',
new DivElement()
..classes = ['memberValue']
..text = ext
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'collections',
new DivElement()
..classes = ['memberValue']
..text = collections
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'average collection time',
new DivElement()
..classes = ['memberValue']
..text = avgCollectionTime
],
];
}
Future _refresh({bool gc = false, bool reset = false}) async {
_profile = null;
_r.dirty();
_profile = await _repository.get(_isolate, gc: gc, reset: reset);
_r.dirty();
}
void _downloadCSV() {
assert(_profile != null);
final header = [
'"New Internal"',
'"New External"',
'"New Size"',
'"New Instances"',
'"Old Internal"',
'"Old External"',
'"Old Size"',
'"Old Instances"',
'"Internal"',
'"External"',
'"Size"',
'"Instances"',
'Class'
].join(',') +
'\n';
AnchorElement tl = document.createElement('a');
tl
..attributes['href'] = 'data:text/plain;charset=utf-8,' +
Uri.encodeComponent(header +
(_profile.members.toList()..sort(_createSorter()))
.map(_csvOut)
.join('\n'))
..attributes['download'] = 'heap-profile.csv'
..click();
}
static _csvOut(M.ClassHeapStats s) {
return [
_getNewInternalSize(s),
_getNewExternalSize(s),
_getNewSize(s),
_getNewInstances(s),
_getOldInternalSize(s),
_getOldExternalSize(s),
_getOldSize(s),
_getOldInstances(s),
_getInternalSize(s),
_getExternalSize(s),
_getSize(s),
_getInstances(s),
s.clazz.name
].join(',');
}
static int _getNewInstances(M.ClassHeapStats s) => s.newSpace.instances;
static int _getNewInternalSize(M.ClassHeapStats s) => s.newSpace.internalSize;
static int _getNewExternalSize(M.ClassHeapStats s) => s.newSpace.externalSize;
static int _getNewSize(M.ClassHeapStats s) => s.newSpace.size;
static int _getOldInstances(M.ClassHeapStats s) => s.oldSpace.instances;
static int _getOldInternalSize(M.ClassHeapStats s) => s.oldSpace.internalSize;
static int _getOldExternalSize(M.ClassHeapStats s) => s.oldSpace.externalSize;
static int _getOldSize(M.ClassHeapStats s) => s.oldSpace.size;
static int _getInstances(M.ClassHeapStats s) =>
s.newSpace.instances + s.oldSpace.instances;
static int _getInternalSize(M.ClassHeapStats s) =>
s.newSpace.internalSize + s.oldSpace.internalSize;
static int _getExternalSize(M.ClassHeapStats s) =>
s.newSpace.externalSize + s.oldSpace.externalSize;
static int _getSize(M.ClassHeapStats s) => s.newSpace.size + s.oldSpace.size;
}

View file

@ -1,120 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/sample_buffer_control.dart';
import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
class ClassAllocationProfileElement extends CustomElement
implements Renderable {
RenderingScheduler<ClassAllocationProfileElement> _r;
Stream<RenderedEvent<ClassAllocationProfileElement>> get onRendered =>
_r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.Class _cls;
M.ClassSampleProfileRepository _profiles;
Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
M.SampleProfileLoadingProgress _progress;
M.SampleProfileTag _tag = M.SampleProfileTag.none;
ProfileTreeMode _mode = ProfileTreeMode.function;
M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
M.IsolateRef get isolate => _isolate;
M.Class get cls => _cls;
factory ClassAllocationProfileElement(M.VM vm, M.IsolateRef isolate,
M.Class cls, M.ClassSampleProfileRepository profiles,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(cls != null);
assert(profiles != null);
ClassAllocationProfileElement e =
new ClassAllocationProfileElement.created();
e._r =
new RenderingScheduler<ClassAllocationProfileElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._cls = cls;
e._profiles = profiles;
return e;
}
ClassAllocationProfileElement.created()
: super.created('class-allocation-profile');
@override
void attached() {
super.attached();
_r.enable();
_request();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
if (_progress == null) {
children = const [];
return;
}
final content = <HtmlElement>[
(new SampleBufferControlElement(_vm, _progress, _progressStream,
selectedTag: _tag, queue: _r.queue)
..onTagChange.listen((e) {
_tag = e.element.selectedTag;
_request(forceFetch: true);
}))
.element
];
if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
CpuProfileVirtualTreeElement tree;
content.addAll([
new BRElement(),
(new StackTraceTreeConfigElement(
mode: _mode,
direction: _direction,
showFilter: false,
queue: _r.queue)
..onModeChange.listen((e) {
_mode = tree.mode = e.element.mode;
})
..onDirectionChange.listen((e) {
_direction = tree.direction = e.element.direction;
}))
.element,
new BRElement(),
(tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
queue: _r.queue))
.element
]);
}
children = content;
}
Future _request({bool forceFetch = false}) async {
_progress = null;
_progressStream =
_profiles.get(_isolate, _cls, _tag, forceFetch: forceFetch);
_r.dirty();
_progress = (await _progressStream.first).progress;
_r.dirty();
if (M.isSampleProcessRunning(_progress.status)) {
_progress = (await _progressStream.last).progress;
_r.dirty();
}
}
}

View file

@ -1,322 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/sentinel_value.dart';
import 'package:observatory_2/src/elements/strongly_reachable_instances.dart';
import 'package:observatory_2/utils.dart';
class ClassInstancesElement extends CustomElement implements Renderable {
RenderingScheduler<ClassInstancesElement> _r;
Stream<RenderedEvent<ClassInstancesElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.Class _cls;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.StronglyReachableInstancesRepository _stronglyReachableInstances;
M.ObjectRepository _objects;
M.Guarded<M.InstanceRef> _allInstances = null;
bool _loadingAllInstances = false;
M.Guarded<M.InstanceRef> _allSubclassInstances = null;
bool _loadingAllSubclassInstances = false;
M.Guarded<M.InstanceRef> _allImplementorInstances = null;
bool _loadingAllImplementorInstances = false;
M.Guarded<M.Instance> _retainedSize = null;
bool _loadingRetainedBytes = false;
M.Guarded<M.Instance> _reachableSize = null;
bool _loadingReachableBytes = false;
M.IsolateRef get isolate => _isolate;
M.Class get cls => _cls;
factory ClassInstancesElement(
M.IsolateRef isolate,
M.Class cls,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.StronglyReachableInstancesRepository stronglyReachableInstances,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(isolate != null);
assert(cls != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(stronglyReachableInstances != null);
assert(objects != null);
ClassInstancesElement e = new ClassInstancesElement.created();
e._r = new RenderingScheduler<ClassInstancesElement>(e, queue: queue);
e._isolate = isolate;
e._cls = cls;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._stronglyReachableInstances = stronglyReachableInstances;
e._objects = objects;
return e;
}
ClassInstancesElement.created() : super.created('class-instances');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
StronglyReachableInstancesElement _strong;
void render() {
_strong = _strong ??
new StronglyReachableInstancesElement(
_isolate, _cls, _stronglyReachableInstances, _objects,
queue: _r.queue);
final instanceCount = _cls.newSpace.instances + _cls.oldSpace.instances;
final size = Utils.formatSize(_cls.newSpace.size + _cls.oldSpace.size);
children = <Element>[
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = const ['memberItem']
..children = <Element>[
new DivElement()
..classes = const ['memberName']
..text = 'currently allocated',
new DivElement()
..classes = const ['memberValue']
..text = 'count ${instanceCount} (shallow size ${size})'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'strongly reachable ',
new DivElement()
..classes = ['memberValue']
..children = <Element>[_strong.element]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'all direct instances'
..title = 'All instances whose class is exactly this class',
new DivElement()
..classes = ['memberValue']
..children = _createAllInstances()
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'all instances of subclasses'
..title =
'All instances whose class is a subclass of this class',
new DivElement()
..classes = ['memberValue']
..children = _createAllSubclassInstances()
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'all instances of implementors'
..title =
'All instances whose class implements the implicit interface of this class',
new DivElement()
..classes = ['memberValue']
..children = _createAllImplementorInstances()
],
new DivElement()
..classes = ['memberItem']
..title = 'Space reachable from this object, '
'excluding class references'
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Reachable size ',
new DivElement()
..classes = ['memberValue']
..children = _createReachableSizeValue()
],
new DivElement()
..classes = ['memberItem']
..title = 'Space that would be reclaimed if references to this '
'object were replaced with null'
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Retained size ',
new DivElement()
..classes = ['memberValue']
..children = _createRetainedSizeValue()
],
]
];
}
List<Element> _createAllInstances() {
final content = <Element>[];
if (_allInstances != null) {
if (_allInstances.isSentinel) {
content.add(
new SentinelValueElement(_allInstances.asSentinel, queue: _r.queue)
.element);
} else {
content.add(anyRef(_isolate, _allInstances.asValue, _objects));
}
} else {
content.add(new SpanElement()..text = '...');
}
final button = new ButtonElement()
..classes = ['reachable_size']
..disabled = _loadingAllInstances
..text = '';
button.onClick.listen((_) async {
button.disabled = true;
_loadingAllInstances = true;
_allInstances =
await _stronglyReachableInstances.getAsArray(_isolate, _cls);
_loadingAllInstances = false;
_r.dirty();
});
content.add(button);
return content;
}
List<Element> _createAllSubclassInstances() {
final content = <Element>[];
if (_allSubclassInstances != null) {
if (_allSubclassInstances.isSentinel) {
content.add(new SentinelValueElement(_allSubclassInstances.asSentinel,
queue: _r.queue)
.element);
} else {
content.add(anyRef(_isolate, _allSubclassInstances.asValue, _objects));
}
} else {
content.add(new SpanElement()..text = '...');
}
final button = new ButtonElement()
..classes = ['reachable_size']
..disabled = _loadingAllSubclassInstances
..text = '';
button.onClick.listen((_) async {
button.disabled = true;
_loadingAllSubclassInstances = true;
_allSubclassInstances = await _stronglyReachableInstances
.getAsArray(_isolate, _cls, includeSubclasses: true);
_loadingAllSubclassInstances = false;
_r.dirty();
});
content.add(button);
return content;
}
List<Element> _createAllImplementorInstances() {
final content = <Element>[];
if (_allImplementorInstances != null) {
if (_allImplementorInstances.isSentinel) {
content.add(new SentinelValueElement(
_allImplementorInstances.asSentinel,
queue: _r.queue)
.element);
} else {
content
.add(anyRef(_isolate, _allImplementorInstances.asValue, _objects));
}
} else {
content.add(new SpanElement()..text = '...');
}
final button = new ButtonElement()
..classes = ['reachable_size']
..disabled = _loadingAllImplementorInstances
..text = '';
button.onClick.listen((_) async {
button.disabled = true;
_loadingAllImplementorInstances = true;
_allImplementorInstances = await _stronglyReachableInstances
.getAsArray(_isolate, _cls, includeImplementors: true);
_loadingAllImplementorInstances = false;
_r.dirty();
});
content.add(button);
return content;
}
List<Element> _createReachableSizeValue() {
final content = <Element>[];
if (_reachableSize != null) {
if (_reachableSize.isSentinel) {
content.add(
new SentinelValueElement(_reachableSize.asSentinel, queue: _r.queue)
.element);
} else {
content.add(new SpanElement()
..text = Utils.formatSize(
int.parse(_reachableSize.asValue.valueAsString)));
}
} else {
content.add(new SpanElement()..text = '...');
}
final button = new ButtonElement()
..classes = ['reachable_size']
..disabled = _loadingReachableBytes
..text = '';
button.onClick.listen((_) async {
button.disabled = true;
_loadingReachableBytes = true;
_reachableSize = await _reachableSizes.get(_isolate, _cls.id);
_r.dirty();
});
content.add(button);
return content;
}
List<Element> _createRetainedSizeValue() {
final content = <Element>[];
if (_retainedSize != null) {
if (_retainedSize.isSentinel) {
content.add(
new SentinelValueElement(_retainedSize.asSentinel, queue: _r.queue)
.element);
} else {
content.add(new SpanElement()
..text =
Utils.formatSize(int.parse(_retainedSize.asValue.valueAsString)));
}
} else {
content.add(new SpanElement()..text = '...');
}
final button = new ButtonElement()
..classes = ['retained_size']
..disabled = _loadingRetainedBytes
..text = '';
button.onClick.listen((_) async {
button.disabled = true;
_loadingRetainedBytes = true;
_retainedSize = await _retainedSizes.get(_isolate, _cls.id);
_r.dirty();
});
content.add(button);
return content;
}
}

View file

@ -1,57 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class ClassRefElement extends CustomElement implements Renderable {
RenderingScheduler<ClassRefElement> _r;
Stream<RenderedEvent<ClassRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.ClassRef _class;
M.IsolateRef get isolate => _isolate;
M.ClassRef get cls => _class;
factory ClassRefElement(M.IsolateRef isolate, M.ClassRef cls,
{RenderingQueue queue}) {
assert(cls != null);
ClassRefElement e = new ClassRefElement.created();
e._r = new RenderingScheduler<ClassRefElement>(e, queue: queue);
e._isolate = isolate;
e._class = cls;
return e;
}
ClassRefElement.created() : super.created('class-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
new AnchorElement(
href: (_isolate == null)
? null
: Uris.inspect(_isolate, object: _class))
..text = _class.name
];
}
}

View file

@ -1,188 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library class_tree_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
class ClassTreeElement extends CustomElement implements Renderable {
RenderingScheduler<ClassTreeElement> _r;
Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered;
M.VMRef _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.ClassRepository _classes;
M.Class _object;
final _subclasses = <String, Iterable<M.Class>>{};
final _mixins = <String, List<M.Instance>>{};
factory ClassTreeElement(
M.VMRef vm,
M.IsolateRef isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.ClassRepository classes,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(classes != null);
ClassTreeElement e = new ClassTreeElement.created();
e._r = new RenderingScheduler<ClassTreeElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._classes = classes;
return e;
}
ClassTreeElement.created() : super.created('class-tree');
@override
void attached() {
super.attached();
_refresh();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
VirtualTreeElement _tree;
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('class hierarchy'),
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered']
..children = <Element>[
new HeadingElement.h1()
..text = 'Class Hierarchy (${_subclasses.length})',
new BRElement(),
new HRElement(),
_object == null
? (new HeadingElement.h2()..text = 'Loading...')
: _createTree()
]
];
}
Element _createTree() {
_tree = new VirtualTreeElement(_create, _update, _children,
items: [_object], search: _search, queue: _r.queue);
_tree.expand(_object, autoExpandSingleChildNodes: true);
return _tree.element;
}
Future _refresh() async {
_object = null;
_subclasses.clear();
_mixins.clear();
_object = await _register(await _classes.getObject(_isolate));
_r.dirty();
}
Future<M.Class> _register(M.Class cls) async {
_subclasses[cls.id] = await Future.wait(
(await Future.wait(cls.subclasses.map(_getActualChildren)))
.expand((f) => f)
.map(_register));
return cls;
}
Future<Iterable<M.Class>> _getActualChildren(M.ClassRef ref) async {
var cls = await _classes.get(_isolate, ref.id);
if (cls.isPatch) {
return const [];
}
if (cls.mixin == null) {
return [cls];
}
return (await Future.wait(cls.subclasses.map(_getActualChildren)))
.expand((f) => f)
..forEach((subcls) {
_mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(cls.mixin);
});
}
static HtmlElement _create(toggle) {
return new DivElement()
..classes = ['class-tree-item']
..children = <Element>[
new SpanElement()..classes = ['lines'],
new ButtonElement()
..classes = ['expander']
..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
new SpanElement()..classes = ['name']
];
}
void _update(HtmlElement el, classDynamic, int index) {
M.Class cls = classDynamic;
virtualTreeUpdateLines(el.children[0], index);
if (cls.subclasses.isEmpty) {
el.children[1].text = '';
} else {
el.children[1].text = _tree.isExpanded(cls) ? '' : '';
}
el.children[2].children = <Element>[
new ClassRefElement(_isolate, cls, queue: _r.queue).element
];
if (_mixins[cls.id] != null) {
el.children[2].children.addAll(_createMixins(_mixins[cls.id]));
}
}
bool _search(Pattern pattern, classDynamic) {
M.Class cls = classDynamic;
return cls.name.contains(pattern);
}
List<Element> _createMixins(List<M.Instance> types) {
final children = types
.expand((type) => <Element>[
new SpanElement()..text = ', ',
type.typeClass == null
? (new SpanElement()..text = type.name.split('<').first)
: new ClassRefElement(_isolate, type.typeClass,
queue: _r.queue)
.element
])
.toList();
children.first.text = ' with ';
return children;
}
Iterable<M.Class> _children(classDynamic) {
M.Class cls = classDynamic;
return _subclasses[cls.id];
}
}

View file

@ -1,492 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library class_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_allocation_profile.dart';
import 'package:observatory_2/src/elements/class_instances.dart';
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/error_ref.dart';
import 'package:observatory_2/src/elements/eval_box.dart';
import 'package:observatory_2/src/elements/field_ref.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
import 'package:observatory_2/src/elements/library_ref.dart';
import 'package:observatory_2/src/elements/nav/class_menu.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/source_inset.dart';
import 'package:observatory_2/src/elements/source_link.dart';
class ClassViewElement extends CustomElement implements Renderable {
RenderingScheduler<ClassViewElement> _r;
Stream<RenderedEvent<ClassViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Class _cls;
M.ClassRepository _classes;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.StronglyReachableInstancesRepository _stronglyReachableInstances;
M.FieldRepository _fields;
M.ScriptRepository _scripts;
M.ObjectRepository _objects;
M.EvalRepository _eval;
M.ClassSampleProfileRepository _profiles;
Iterable<M.Field> _classFields;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Class get cls => _cls;
factory ClassViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Class cls,
M.EventRepository events,
M.NotificationRepository notifications,
M.ClassRepository classes,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.FieldRepository fields,
M.ScriptRepository scripts,
M.ObjectRepository objects,
M.EvalRepository eval,
M.StronglyReachableInstancesRepository stronglyReachable,
M.ClassSampleProfileRepository profiles,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(cls != null);
assert(classes != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(fields != null);
assert(scripts != null);
assert(objects != null);
assert(eval != null);
assert(stronglyReachable != null);
assert(profiles != null);
ClassViewElement e = new ClassViewElement.created();
e._r = new RenderingScheduler<ClassViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._cls = cls;
e._classes = classes;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._fields = fields;
e._scripts = scripts;
e._objects = objects;
e._eval = eval;
e._stronglyReachableInstances = stronglyReachable;
e._profiles = profiles;
return e;
}
ClassViewElement.created() : super.created('class-view');
@override
attached() {
super.attached();
_r.enable();
_loadAdditionalData();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
ObjectCommonElement _common;
ClassInstancesElement _classInstances;
bool _loadProfile = false;
void render() {
_common = _common ??
new ObjectCommonElement(_isolate, _cls, _retainedSizes, _reachableSizes,
_references, _retainingPaths, _objects,
queue: _r.queue);
_classInstances = _classInstances ??
new ClassInstancesElement(_isolate, _cls, _retainedSizes,
_reachableSizes, _stronglyReachableInstances, _objects,
queue: _r.queue);
var header = '';
if (_cls.isAbstract) {
header += 'abstract ';
}
if (_cls.isPatch) {
header += 'patch ';
}
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
new NavClassMenuElement(_isolate, _cls, queue: _r.queue).element,
(new NavRefreshElement(
label: 'Refresh Allocation Profile', queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_loadProfile = true;
_r.dirty();
}))
.element,
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_common = null;
_classInstances = null;
_fieldsExpanded = null;
_functionsExpanded = null;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = '$header class ${_cls.name}',
new HRElement(),
_common.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createMembers(),
new DivElement()
..children = _cls.error == null
? const []
: [
new HRElement(),
new ErrorRefElement(_cls.error, queue: _r.queue).element
],
new HRElement(),
new EvalBoxElement(_isolate, _cls, _objects, _eval, queue: _r.queue)
.element,
new HRElement(),
new HeadingElement.h2()..text = 'Fields & Functions',
new DivElement()
..classes = ['memberList']
..children = _createElements(),
new HRElement(),
new HeadingElement.h2()..text = 'Instances',
new DivElement()..children = [_classInstances.element],
new HRElement(),
new HeadingElement.h2()..text = 'Allocations',
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Tracing allocations? ',
new DivElement()
..classes = ['memberValue']
..children = _cls.traceAllocations
? [
new SpanElement()..text = 'Yes ',
new ButtonElement()
..text = 'disable'
..onClick.listen((e) async {
(e.target as ButtonElement).disabled = true;
await _profiles.disable(_isolate, _cls);
_loadProfile = true;
_refresh();
})
]
: [
new SpanElement()..text = 'No ',
new ButtonElement()
..text = 'enable'
..onClick.listen((e) async {
(e.target as ButtonElement).disabled = true;
await _profiles.enable(_isolate, _cls);
_refresh();
})
]
],
new DivElement()
..children = _loadProfile
? [
new ClassAllocationProfileElement(
_vm, _isolate, _cls, _profiles,
queue: _r.queue)
.element
]
: const [],
new DivElement()
..children = _cls.location != null
? [
new HRElement(),
new SourceInsetElement(_isolate, _cls.location, _scripts,
_objects, _events,
queue: _r.queue)
.element
]
: const [],
]
];
}
bool _fieldsExpanded;
bool _functionsExpanded;
List<Element> _createMembers() {
final members = <Element>[];
if (_cls.library != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'library',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new LibraryRefElement(_isolate, _cls.library, queue: _r.queue)
.element
]
]);
}
if (_cls.location != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'script',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new SourceLinkElement(_isolate, _cls.location, _scripts,
queue: _r.queue)
.element
]
]);
}
if (_cls.superclass != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'superclass',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new ClassRefElement(_isolate, _cls.superclass, queue: _r.queue)
.element
]
]);
}
if (_cls.superType != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'supertype',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new InstanceRefElement(_isolate, _cls.superType, _objects,
queue: _r.queue)
.element
]
]);
}
if (cls.mixin != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'mixin',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new InstanceRefElement(_isolate, _cls.mixin, _objects,
queue: _r.queue)
.element
]
]);
}
if (_cls.subclasses.length > 0) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'extended by',
new DivElement()
..classes = ['memberValue']
..children = (_cls.subclasses
.expand((subcls) => <Element>[
new ClassRefElement(_isolate, subcls, queue: _r.queue)
.element,
new SpanElement()..text = ', '
])
.toList()
..removeLast())
]);
}
members.add(new BRElement());
if (_cls.interfaces.length > 0) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'implements',
new DivElement()
..classes = ['memberValue']
..children = (_cls.interfaces
.expand((interf) => <Element>[
new InstanceRefElement(_isolate, interf, _objects,
queue: _r.queue)
.element,
new SpanElement()..text = ', '
])
.toList()
..removeLast())
]);
}
if (_cls.name != _cls.vmName) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'vm name',
new DivElement()
..classes = ['memberValue']
..text = '${_cls.vmName}'
]);
}
return members;
}
List<Element> _createElements() {
final members = <Element>[];
if (_classFields != null && _classFields.isNotEmpty) {
final fields = _classFields.toList();
_fieldsExpanded = _fieldsExpanded ?? (fields.length <= 8);
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'fields ${fields.length}',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(expanded: _fieldsExpanded)
..onToggle
.listen((e) => _fieldsExpanded = e.control.expanded)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = (fields
.map<Element>((f) => new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..children = <Element>[
new FieldRefElement(_isolate, f, _objects,
queue: _r.queue)
.element
],
new DivElement()
..classes = ['memberValue']
..children = f.staticValue == null
? const []
: [
anyRef(
_isolate, f.staticValue, _objects,
queue: _r.queue)
]
])
.toList())
])
.element
]
]);
}
if (_cls.functions.isNotEmpty) {
final functions = _cls.functions.toList();
_functionsExpanded = _functionsExpanded ?? (functions.length <= 8);
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'functions (${functions.length})',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(expanded: _functionsExpanded)
..onToggle
.listen((e) => _functionsExpanded = e.control.expanded)
..content = (functions
.map<Element>((f) => new DivElement()
..classes = ['indent']
..children = <Element>[
new FunctionRefElement(_isolate, f, queue: _r.queue)
.element
])
.toList()))
.element
]
]);
}
return members;
}
Future _refresh() async {
_cls = await _classes.get(_isolate, _cls.id);
await _loadAdditionalData();
_r.dirty();
}
Future _loadAdditionalData() async {
_classFields =
await Future.wait(_cls.fields.map((f) => _fields.get(_isolate, f.id)));
_r.dirty();
}
}

View file

@ -1,60 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library code_ref_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M
show IsolateRef, CodeRef, isSyntheticCode;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class CodeRefElement extends CustomElement implements Renderable {
RenderingScheduler<CodeRefElement> _r;
Stream<RenderedEvent<CodeRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.CodeRef _code;
M.IsolateRef get isolate => _isolate;
M.CodeRef get code => _code;
factory CodeRefElement(M.IsolateRef isolate, M.CodeRef code,
{RenderingQueue queue}) {
assert(code != null);
CodeRefElement e = new CodeRefElement.created();
e._r = new RenderingScheduler<CodeRefElement>(e, queue: queue);
e._isolate = isolate;
e._code = code;
return e;
}
CodeRefElement.created() : super.created('code-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
children = <Element>[
new AnchorElement(
href: ((M.isSyntheticCode(_code.kind)) || (_isolate == null))
? null
: Uris.inspect(_isolate, object: _code))
..text = _code.name
];
}
}

View file

@ -1,641 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library code_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/sample_profile.dart';
import 'package:observatory_2/service.dart' as S;
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/app.dart'
show SortedTable, SortedTableColumn, SortedTableRow;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/objectpool_ref.dart';
import 'package:observatory_2/utils.dart';
class DisassemblyTable extends SortedTable {
DisassemblyTable(columns) : super(columns);
}
class InlineTable extends SortedTable {
InlineTable(columns) : super(columns);
}
class CodeViewElement extends CustomElement implements Renderable {
RenderingScheduler<CodeViewElement> _r;
Stream<RenderedEvent<CodeViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Code _code;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ObjectRepository _objects;
DisassemblyTable disassemblyTable;
InlineTable inlineTable;
static const kDisassemblyColumnIndex = 3;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Code get context => _code;
factory CodeViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Code code,
M.EventRepository events,
M.NotificationRepository notifications,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(code != null);
assert(objects != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
CodeViewElement e = new CodeViewElement.created();
e._r = new RenderingScheduler<CodeViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._code = code;
e._objects = objects;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
return e;
}
CodeViewElement.created() : super.created('code-view') {
var columns = [
new SortedTableColumn('Address'),
new SortedTableColumn('Inclusive'),
new SortedTableColumn('Exclusive'),
new SortedTableColumn('Disassembly'),
new SortedTableColumn('Objects'),
];
disassemblyTable = new DisassemblyTable(columns);
columns = [
new SortedTableColumn('Address'),
new SortedTableColumn('Inclusive'),
new SortedTableColumn('Exclusive'),
new SortedTableColumn('Functions'),
];
inlineTable = new InlineTable(columns);
}
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
TableElement _disassemblyTable;
TableElement _inlineRangeTable;
Element _disassemblyTableBody;
Element _inlineRangeTableBody;
void render() {
if (_inlineRangeTable == null) {
_inlineRangeTable = new TableElement()..classes = ['table'];
_inlineRangeTable.createTHead().children = <Element>[
new TableRowElement()
..children = <Element>[
document.createElement('th')
..classes = ['address']
..text = 'Address Range',
document.createElement('th')
..classes = ['tick']
..text = 'Inclusive',
document.createElement('th')
..classes = ['tick']
..text = 'Exclusive',
document.createElement('th')..text = 'Functions',
]
];
_inlineRangeTableBody = _inlineRangeTable.createTBody();
_inlineRangeTableBody.classes = ['monospace'];
}
if (_disassemblyTable == null) {
_disassemblyTable = new TableElement()..classes = ['table'];
_disassemblyTable.createTHead().children = <Element>[
new TableRowElement()
..children = <Element>[
document.createElement('th')
..classes = ['address']
..text = 'Address Range',
document.createElement('th')
..classes = ['tick']
..title = 'Ticks with PC on the stack'
..text = 'Inclusive',
document.createElement('th')
..classes = ['tick']
..title = 'Ticks with PC at top of stack'
..text = 'Exclusive',
document.createElement('th')
..classes = ['disassembly']
..text = 'Disassembly',
document.createElement('th')
..classes = ['object']
..text = 'Object',
]
];
_disassemblyTableBody = _disassemblyTable.createTBody();
_disassemblyTableBody.classes = ['monospace'];
}
final inlinedFunctions = _code.inlinedFunctions.toList();
final S.Code code = _code as S.Code;
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu(_code.name),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_refresh();
}))
.element,
(new NavRefreshElement(label: 'refresh ticks', queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_refreshTicks();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h1()
..text = (M.isDartCode(_code.kind) && _code.isOptimized)
? 'Optimized code for ${_code.name}'
: 'Code for ${_code.name}',
new HRElement(),
new ObjectCommonElement(_isolate, _code, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Kind',
new DivElement()
..classes = ['memberValue']
..text = _codeKindToString(_code.kind)
],
new DivElement()
..classes = ['memberItem']
..children = M.isDartCode(_code.kind)
? const []
: [
new DivElement()
..classes = ['memberName']
..text = 'Optimized',
new DivElement()
..classes = ['memberValue']
..text = _code.isOptimized ? 'Yes' : 'No'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Function',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new FunctionRefElement(_isolate, _code.function,
queue: _r.queue)
.element
]
],
new DivElement()
..classes = ['memberItem']
..children = code.profile == null
? const []
: [
new DivElement()
..classes = ['memberName']
..text = 'Inclusive',
new DivElement()
..classes = ['memberValue']
..text = '${code.profile.formattedInclusiveTicks}'
],
new DivElement()
..classes = ['memberItem']
..children = code.profile == null
? const []
: [
new DivElement()
..classes = ['memberName']
..text = 'Exclusive',
new DivElement()
..classes = ['memberValue']
..text = '${code.profile.formattedExclusiveTicks}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Object pool',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new ObjectPoolRefElement(_isolate, _code.objectPool,
queue: _r.queue)
.element
]
],
new DivElement()
..classes = ['memberItem']
..children = inlinedFunctions.isNotEmpty
? const []
: [
new DivElement()
..classes = ['memberName']
..text =
'inlined functions (${inlinedFunctions.length})',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(
expanded: inlinedFunctions.length < 8,
queue: _r.queue)
..content = inlinedFunctions
.map<Element>((f) =>
new FunctionRefElement(_isolate, f,
queue: _r.queue)
.element)
.toList())
.element
]
]
],
new HRElement(),
_inlineRangeTable,
new HRElement(),
_disassemblyTable
],
];
_updateDisassembly();
_updateInline();
}
Future _refresh() async {
S.Code code = _code as S.Code;
await code.reload();
_r.dirty();
}
Future _refreshTicks() async {
S.Code code = _code as S.Code;
final isolate = code.isolate;
S.ServiceMap response =
await isolate.invokeRpc('_getCpuProfile', {'tags': 'None'});
final cpuProfile = new SampleProfile();
await cpuProfile.load(isolate, response);
_r.dirty();
}
String _formattedAddress(S.CodeInstruction instruction) {
if (instruction.address == 0) {
return '';
}
return '0x${instruction.address.toRadixString(16)}';
}
String _formattedAddressRange(S.CodeInlineInterval interval) {
String start = interval.start.toRadixString(16);
String end = interval.end.toRadixString(16);
return '[0x$start, 0x$end)';
}
String _formattedInclusiveInterval(S.CodeInlineInterval interval) {
S.Code code = _code as S.Code;
if (code.profile == null) {
return '';
}
var intervalTick = code.profile.intervalTicks[interval.start];
if (intervalTick == null) {
return '';
}
// Don't show inclusive ticks if they are the same as exclusive ticks.
if (intervalTick.inclusiveTicks == intervalTick.exclusiveTicks) {
return '';
}
var pcent = Utils.formatPercent(
intervalTick.inclusiveTicks, code.profile.profile.sampleCount);
return '$pcent (${intervalTick.inclusiveTicks})';
}
String _formattedExclusiveInterval(S.CodeInlineInterval interval) {
S.Code code = _code as S.Code;
if (code.profile == null) {
return '';
}
var intervalTick = code.profile.intervalTicks[interval.start];
if (intervalTick == null) {
return '';
}
var pcent = Utils.formatPercent(
intervalTick.exclusiveTicks, code.profile.profile.sampleCount);
return '$pcent (${intervalTick.exclusiveTicks})';
}
String _formattedInclusive(S.CodeInstruction instruction) {
S.Code code = _code as S.Code;
if (code.profile == null) {
return '';
}
var tick = code.profile.addressTicks[instruction.address];
if (tick == null) {
return '';
}
// Don't show inclusive ticks if they are the same as exclusive ticks.
if (tick.inclusiveTicks == tick.exclusiveTicks) {
return '';
}
var pcent = Utils.formatPercent(
tick.inclusiveTicks, code.profile.profile.sampleCount);
return '$pcent (${tick.inclusiveTicks})';
}
String _formattedExclusive(S.CodeInstruction instruction) {
S.Code code = _code as S.Code;
if (code.profile == null) {
return '';
}
var tick = code.profile.addressTicks[instruction.address];
if (tick == null) {
return '';
}
var pcent = Utils.formatPercent(
tick.exclusiveTicks, code.profile.profile.sampleCount);
return '$pcent (${tick.exclusiveTicks})';
}
void _updateDisassemblyTable() {
S.Code code = _code as S.Code;
disassemblyTable.clearRows();
if (code == null) {
return;
}
for (S.CodeInstruction instruction in code.instructions) {
var row = [
_formattedAddress(instruction),
_formattedInclusive(instruction),
_formattedExclusive(instruction),
instruction.human,
instruction.object
];
disassemblyTable.addRow(new SortedTableRow(row));
}
}
void _addDisassemblyDOMRow() {
var tableBody = _disassemblyTableBody;
assert(tableBody != null);
var tr = new TableRowElement();
var cell;
// Add new space.
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
tableBody.children.add(tr);
}
void _fillDisassemblyDOMRow(TableRowElement tr, int rowIndex) {
final row = disassemblyTable.rows[rowIndex];
final n = row.values.length;
for (var i = 0; i < n; i++) {
final cell = tr.children[i];
final content = row.values[i];
if (content is S.HeapObject) {
cell.children = <Element>[
anyRef(_isolate, content, _objects, queue: _r.queue)
];
} else if (content != null) {
String text = '$content';
if (i == kDisassemblyColumnIndex) {
// Disassembly might be a comment. Reduce indentation, change styling,
// widen to span next column (which should be empty).
if (text.startsWith(' ;;')) {
cell.attributes['colspan'] = '2';
cell.classes.add('code-comment');
text = text.substring(6);
} else {
cell.attributes['colspan'] = '1';
cell.classes.remove('code-comment');
}
}
cell.text = text;
}
}
}
void _updateDisassemblyDOMTable() {
var tableBody = _disassemblyTableBody;
assert(tableBody != null);
// Resize DOM table.
if (tableBody.children.length > disassemblyTable.sortedRows.length) {
// Shrink the table.
var deadRows =
tableBody.children.length - disassemblyTable.sortedRows.length;
for (var i = 0; i < deadRows; i++) {
tableBody.children.removeLast();
}
} else if (tableBody.children.length < disassemblyTable.sortedRows.length) {
// Grow table.
var newRows =
disassemblyTable.sortedRows.length - tableBody.children.length;
for (var i = 0; i < newRows; i++) {
_addDisassemblyDOMRow();
}
}
assert(tableBody.children.length == disassemblyTable.sortedRows.length);
// Fill table.
var i = 0;
for (var tr in tableBody.children) {
var rowIndex = disassemblyTable.sortedRows[i];
_fillDisassemblyDOMRow(tr, rowIndex);
i++;
}
}
void _updateDisassembly() {
_updateDisassemblyTable();
_updateDisassemblyDOMTable();
}
void _updateInlineTable() {
inlineTable.clearRows();
S.Code code = _code as S.Code;
for (S.CodeInlineInterval interval in code.inlineIntervals) {
var row = [
interval,
_formattedInclusiveInterval(interval),
_formattedExclusiveInterval(interval),
interval.functions
];
inlineTable.addRow(new SortedTableRow(row));
}
}
void _addInlineDOMRow() {
var tableBody = _inlineRangeTableBody;
assert(tableBody != null);
var tr = new TableRowElement();
var cell;
// Add new space.
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
cell.classes.add('monospace');
cell = tr.insertCell(-1);
tableBody.children.add(tr);
}
void _fillInlineDOMRow(TableRowElement tr, int rowIndex) {
var row = inlineTable.rows[rowIndex];
var columns = row.values.length;
var addressRangeColumn = 0;
var functionsColumn = columns - 1;
{
var addressRangeCell = tr.children[addressRangeColumn];
var interval = row.values[addressRangeColumn];
var addressRangeString = _formattedAddressRange(interval);
var addressRangeElement = new SpanElement();
addressRangeElement.classes.add('monospace');
addressRangeElement.text = addressRangeString;
addressRangeCell.children.clear();
addressRangeCell.children.add(addressRangeElement);
}
for (var i = addressRangeColumn + 1; i < columns - 1; i++) {
var cell = tr.children[i];
cell.text = row.values[i].toString();
}
var functions = row.values[functionsColumn];
var functionsCell = tr.children[functionsColumn];
functionsCell.children.clear();
for (var func in functions) {
functionsCell.children
.add(new FunctionRefElement(_isolate, func, queue: _r.queue).element);
var gap = new SpanElement();
gap.style.minWidth = '1em';
gap.text = ' ';
functionsCell.children.add(gap);
}
}
void _updateInlineDOMTable() {
var tableBody = _inlineRangeTableBody;
// Resize DOM table.
if (tableBody.children.length > inlineTable.sortedRows.length) {
// Shrink the table.
var deadRows = tableBody.children.length - inlineTable.sortedRows.length;
for (var i = 0; i < deadRows; i++) {
tableBody.children.removeLast();
}
} else if (tableBody.children.length < inlineTable.sortedRows.length) {
// Grow table.
var newRows = inlineTable.sortedRows.length - tableBody.children.length;
for (var i = 0; i < newRows; i++) {
_addInlineDOMRow();
}
}
assert(tableBody.children.length == inlineTable.sortedRows.length);
// Fill table.
for (var i = 0; i < inlineTable.sortedRows.length; i++) {
var rowIndex = inlineTable.sortedRows[i];
var tr = tableBody.children[i];
_fillInlineDOMRow(tr, rowIndex);
}
}
void _updateInline() {
_updateInlineTable();
_updateInlineDOMTable();
}
static String _codeKindToString(M.CodeKind kind) {
switch (kind) {
case M.CodeKind.dart:
return 'dart';
case M.CodeKind.native:
return 'native';
case M.CodeKind.stub:
return 'stub';
case M.CodeKind.tag:
return 'tag';
case M.CodeKind.collected:
return 'collected';
}
throw new Exception('Unknown CodeKind ($kind)');
}
}

View file

@ -1,205 +0,0 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'dart:math' as math;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class SearchResultSelected {
final SearchBarElement element;
final dynamic item;
SearchResultSelected(this.element, this.item);
}
typedef Iterable<dynamic> SearchBarSearchCallback(Pattern pattern);
class SearchBarElement extends CustomElement implements Renderable {
RenderingScheduler<SearchBarElement> _r;
StreamController<SearchResultSelected> _onSearchResultSelected =
new StreamController<SearchResultSelected>.broadcast();
Stream<RenderedEvent<SearchBarElement>> get onRendered => _r.onRendered;
Stream<SearchResultSelected> get onSearchResultSelected =>
_onSearchResultSelected.stream;
StreamSubscription _onKeyDownSubscription;
Element _workspace;
SearchBarSearchCallback _search;
bool _isOpen;
bool _focusRequested = false;
String _lastValue = '';
List _results = const [];
int _current = 0;
bool get isOpen => _isOpen;
dynamic get current => _results.isNotEmpty ? _results[_current] : null;
set isOpen(bool value) {
if (!value) {
_input.value = '';
_lastValue = '';
if (_results.isNotEmpty) {
_results = const [];
_current = 0;
_triggerSearchResultSelected();
}
}
_isOpen = _r.checkAndReact(_isOpen, value);
}
factory SearchBarElement(SearchBarSearchCallback search,
{bool isOpen = false, Element workspace, RenderingQueue queue}) {
assert(search != null);
assert(isOpen != null);
SearchBarElement e = new SearchBarElement.created();
e._r = new RenderingScheduler<SearchBarElement>(e, queue: queue);
e._search = search;
e._isOpen = isOpen;
e._workspace = workspace;
return e;
}
SearchBarElement.created() : super.created('search-bar');
@override
attached() {
super.attached();
_r.enable();
_workspace?.tabIndex = 1;
_onKeyDownSubscription = (_workspace ?? window).onKeyDown.listen((e) {
if (e.key.toLowerCase() == 'f' &&
!e.shiftKey &&
!e.altKey &&
e.ctrlKey != e.metaKey) {
if (e.metaKey == window.navigator.platform.startsWith('Mac')) {
e.stopPropagation();
e.preventDefault();
isOpen = true;
_focusRequested = true;
_r.dirty();
}
}
});
}
@override
detached() {
super.detached();
_r.disable(notify: true);
_onKeyDownSubscription.cancel();
}
TextInputElement _input;
SpanElement _resultsArea;
void render() {
if (_input == null) {
_input = new TextInputElement()
..onKeyPress.listen((e) {
if (e.keyCode == KeyCode.ENTER) {
if (_input.value == '') {
_lastValue = '';
if (_results.isNotEmpty) {
_results = const [];
_current = 0;
_triggerSearchResultSelected();
_r.dirty();
}
} else if (_input.value != _lastValue) {
_lastValue = _input.value;
_results = _doSearch(_input.value);
_current = 0;
_triggerSearchResultSelected();
_r.dirty();
} else {
if (e.shiftKey) {
_prev();
} else {
_next();
}
}
}
});
_resultsArea = new SpanElement();
children = <Element>[
_input,
_resultsArea,
new ButtonElement()
..text = ''
..onClick.listen((_) {
isOpen = false;
})
];
}
_resultsArea.nodes = [
new ButtonElement()
..text = ''
..disabled = _results.isEmpty
..onClick.listen((_) => _prev()),
new Text(
'${math.min(_current + 1, _results.length)} / ${_results.length}'),
new ButtonElement()
..text = ''
..disabled = _results.isEmpty
..onClick.listen((_) => _next()),
];
style.visibility = isOpen ? null : 'collapse';
if (_focusRequested) {
_input.focus();
_focusRequested = false;
}
}
void update() {
if (!isOpen || _lastValue == '') {
return;
}
final item = current;
_results = _doSearch(_lastValue);
_current = math.max(0, _results.indexOf(item));
_r.dirty();
}
List<dynamic> _doSearch(String value) =>
_search(new _CaseInsensitivePatternString(value)).toList(growable: false);
void _prev() {
if (_results.isEmpty) {
return;
}
_current = (_current + _results.length - 1) % _results.length;
_triggerSearchResultSelected();
_r.dirty();
}
void _next() {
if (_results.isEmpty) {
return;
}
_current = (_current + 1) % _results.length;
_triggerSearchResultSelected();
_r.dirty();
}
void _triggerSearchResultSelected() {
_onSearchResultSelected.add(new SearchResultSelected(this, current));
}
}
class _CaseInsensitivePatternString implements Pattern {
final String _pattern;
_CaseInsensitivePatternString(String pattern)
: this._pattern = pattern.toLowerCase();
Iterable<Match> allMatches(String string, [int start = 0]) =>
_pattern.allMatches(string.toLowerCase(), start);
Match matchAsPrefix(String string, [int start = 0]) =>
_pattern.matchAsPrefix(string.toLowerCase(), start);
}

View file

@ -1,259 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'dart:math' as math;
import 'package:observatory_2/src/elements/containers/search_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
typedef HtmlElement VirtualCollectionCreateCallback();
typedef List<HtmlElement> VirtualCollectionHeaderCallback();
typedef void VirtualCollectionUpdateCallback(
HtmlElement el, dynamic item, int index);
typedef bool VirtualCollectionSearchCallback(Pattern pattern, dynamic item);
class VirtualCollectionElement extends CustomElement implements Renderable {
RenderingScheduler<VirtualCollectionElement> _r;
Stream<RenderedEvent<VirtualCollectionElement>> get onRendered =>
_r.onRendered;
VirtualCollectionCreateCallback _create;
VirtualCollectionHeaderCallback _createHeader;
VirtualCollectionUpdateCallback _update;
VirtualCollectionSearchCallback _search;
double _itemHeight;
int _top;
double _height;
List _items;
StreamSubscription _onScrollSubscription;
StreamSubscription _onResizeSubscription;
List get items => _items;
set items(Iterable value) {
_items = new List.unmodifiable(value);
_top = null;
_searcher?.update();
_r.dirty();
}
factory VirtualCollectionElement(VirtualCollectionCreateCallback create,
VirtualCollectionUpdateCallback update,
{Iterable items = const [],
VirtualCollectionHeaderCallback createHeader,
VirtualCollectionSearchCallback search,
RenderingQueue queue}) {
assert(create != null);
assert(update != null);
assert(items != null);
VirtualCollectionElement e = new VirtualCollectionElement.created();
e._r = new RenderingScheduler<VirtualCollectionElement>(e, queue: queue);
e._create = create;
e._createHeader = createHeader;
e._update = update;
e._search = search;
e._items = new List.unmodifiable(items);
return e;
}
VirtualCollectionElement.created() : super.created('virtual-collection');
@override
attached() {
super.attached();
_r.enable();
_top = null;
_itemHeight = null;
_onScrollSubscription = _viewport.onScroll.listen(_onScroll);
_onResizeSubscription = window.onResize.listen(_onResize);
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = const [];
_onScrollSubscription.cancel();
_onResizeSubscription.cancel();
}
DivElement _header;
SearchBarElement _searcher;
final DivElement _viewport = new DivElement()
..classes = ['viewport', 'container'];
final DivElement _spacer = new DivElement()..classes = ['spacer'];
final DivElement _buffer = new DivElement()..classes = ['buffer'];
static int safeFloor(double x) {
if (x.isNaN) return 0;
return x.floor();
}
static int safeCeil(double x) {
if (x.isNaN) return 0;
return x.ceil();
}
dynamic getItemFromElement(HtmlElement element) {
final el_index = _buffer.children.indexOf(element);
if (el_index < 0) {
return null;
}
final item_index =
_top + el_index - safeFloor(_buffer.children.length * _inverse_preload);
if (0 <= item_index && item_index < items.length) {
return _items[item_index];
}
return null;
}
/// The preloaded element before and after the visible area are:
/// 1/preload_size of the number of items in the visible area.
static const int _preload = 2;
/// L = length of all the elements loaded
/// l = length of the visible area
///
/// L = l + 2 * l / _preload
/// l = L * _preload / (_preload + 2)
///
/// tail = l / _preload = L * 1 / (_preload + 2) = L * _inverse_preload
static const double _inverse_preload = 1 / (_preload + 2);
var _takeIntoView;
void takeIntoView(item) {
_takeIntoView = item;
_r.dirty();
}
void render() {
if (children.isEmpty) {
children = <Element>[
_viewport
..children = <Element>[
_spacer
..children = <Element>[
_buffer..children = <Element>[_create()]
],
]
];
if (_search != null) {
_searcher =
_searcher ?? new SearchBarElement(_doSearch, queue: _r.queue)
..onSearchResultSelected.listen((e) {
takeIntoView(e.item);
});
children.insert(0, _searcher.element);
}
if (_createHeader != null) {
_header = new DivElement()
..classes = ['header', 'container']
..children = _createHeader();
children.insert(0, _header);
final rect = _header.getBoundingClientRect();
_header.classes.add('attached');
_viewport.style.top = '${rect.height}px';
final width = _header.children.fold(0.0, _foldWidth);
_buffer.style.minWidth = '${width}px';
}
_itemHeight = _buffer.children[0].getBoundingClientRect().height;
_height = getBoundingClientRect().height;
}
if (_takeIntoView != null) {
final index = items.indexOf(_takeIntoView);
if (index >= 0) {
final minScrollTop = _itemHeight * (index + 1) - _height;
final maxScrollTop = _itemHeight * index;
_viewport.scrollTop =
safeFloor((maxScrollTop - minScrollTop) / 2 + minScrollTop);
}
_takeIntoView = null;
}
final top = safeFloor(_viewport.scrollTop / _itemHeight);
_spacer.style.height = '${_itemHeight * (_items.length)}px';
final tail_length = safeCeil(_height / _itemHeight / _preload);
final length = tail_length * 2 + tail_length * _preload;
if (_buffer.children.length < length) {
while (_buffer.children.length != length) {
var e = _create();
e..style.display = 'hidden';
_buffer.children.add(e);
}
_top = null; // force update;
}
if ((_top == null) || ((top - _top).abs() >= tail_length)) {
_buffer.style.top = '${_itemHeight * (top - tail_length)}px';
int i = top - tail_length;
for (final HtmlElement e in _buffer.children) {
if (0 <= i && i < _items.length) {
e.style.display = null;
_update(e, _items[i], i);
} else {
e.style.display = 'hidden';
}
i++;
}
_top = top;
}
if (_searcher != null) {
final current = _searcher.current;
int i = _top - tail_length;
for (final HtmlElement e in _buffer.children) {
if (0 <= i && i < _items.length) {
if (_items[i] == current) {
e.classes.add('marked');
} else {
e.classes.remove('marked');
}
}
i++;
}
}
_updateHeader();
}
double _foldWidth(double value, Element child) {
return math.max(value, child.getBoundingClientRect().width);
}
void _updateHeader() {
if (_header != null) {
_header.style.left = '${-_viewport.scrollLeft}px';
final width = _buffer.getBoundingClientRect().width;
_header.children.last.style.width = '${width}px';
}
}
void _onScroll(_) {
_r.dirty();
// We anticipate the header in advance to avoid flickering
_updateHeader();
}
void _onResize(_) {
final newHeight = getBoundingClientRect().height;
if (newHeight > _height) {
_height = newHeight;
_r.dirty();
} else {
// Even if we are not updating the structure the computed size is going to
// change
_updateHeader();
}
}
Iterable<dynamic> _doSearch(Pattern search) {
return _items.where((item) => _search(search, item));
}
}

View file

@ -1,183 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'dart:collection';
import 'dart:math' as Math;
import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
typedef HtmlElement VirtualTreeCreateCallback(
toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree}));
typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth);
typedef Iterable<dynamic> VirtualTreeGetChildrenCallback(dynamic value);
typedef bool VirtualTreeSearchCallback(Pattern pattern, dynamic item);
void virtualTreeUpdateLines(SpanElement element, int n) {
n = Math.max(0, n);
while (element.children.length > n) {
element.children.removeLast();
}
while (element.children.length < n) {
element.children.add(new SpanElement());
}
}
class VirtualTreeElement extends CustomElement implements Renderable {
RenderingScheduler<VirtualTreeElement> _r;
Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered;
VirtualTreeGetChildrenCallback _children;
List _items;
List _depths;
final Set _expanded = new Set();
List get items => _items;
set items(Iterable value) {
_items = new List.unmodifiable(value);
_expanded.clear();
_r.dirty();
}
factory VirtualTreeElement(VirtualTreeCreateCallback create,
VirtualTreeUpdateCallback update, VirtualTreeGetChildrenCallback children,
{Iterable items = const [],
VirtualTreeSearchCallback search,
RenderingQueue queue}) {
assert(create != null);
assert(update != null);
assert(children != null);
assert(items != null);
VirtualTreeElement e = new VirtualTreeElement.created();
e._r = new RenderingScheduler<VirtualTreeElement>(e, queue: queue);
e._children = children;
e._collection = new VirtualCollectionElement(() {
var element;
return element = create((
{bool autoToggleSingleChildNodes = false,
bool autoToggleWholeTree = false}) {
var item = e._collection.getItemFromElement(element);
if (e.isExpanded(item)) {
e.collapse(item,
autoCollapseWholeTree: autoToggleWholeTree,
autoCollapseSingleChildNodes: autoToggleSingleChildNodes);
} else {
e.expand(item,
autoExpandWholeTree: autoToggleWholeTree,
autoExpandSingleChildNodes: autoToggleSingleChildNodes);
}
});
}, (HtmlElement el, dynamic item, int index) {
update(el, item, e._depths[index]);
}, search: search, queue: queue);
e._items = new List.unmodifiable(items);
return e;
}
VirtualTreeElement.created() : super.created('virtual-tree');
bool isExpanded(item) {
return _expanded.contains(item);
}
void expand(item,
{bool autoExpandSingleChildNodes = false,
bool autoExpandWholeTree = false}) {
if (_expanded.add(item)) _r.dirty();
if (autoExpandWholeTree) {
// The tree is potentially very deep, simple recursion can produce a
// Stack Overflow
Queue pendingNodes = new Queue();
pendingNodes.addAll(_children(item));
while (pendingNodes.isNotEmpty) {
final item = pendingNodes.removeFirst();
if (_expanded.add(item)) _r.dirty();
pendingNodes.addAll(_children(item));
}
} else if (autoExpandSingleChildNodes) {
var children = _children(item);
while (children.length == 1) {
_expanded.add(children.first);
children = _children(children.first);
}
}
}
void collapse(item,
{bool autoCollapseSingleChildNodes = false,
bool autoCollapseWholeTree = false}) {
if (_expanded.remove(item)) _r.dirty();
if (autoCollapseWholeTree) {
// The tree is potentially very deep, simple recursion can produce a
// Stack Overflow
Queue pendingNodes = new Queue();
pendingNodes.addAll(_children(item));
while (pendingNodes.isNotEmpty) {
final item = pendingNodes.removeFirst();
if (_expanded.remove(item)) _r.dirty();
pendingNodes.addAll(_children(item));
}
} else if (autoCollapseSingleChildNodes) {
var children = _children(item);
while (children.length == 1) {
_expanded.remove(children.first);
children = _children(children.first);
}
}
}
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = const [];
}
VirtualCollectionElement _collection;
void render() {
if (children.length == 0) {
children = <Element>[_collection.element];
}
final items = [];
final depths = new List.filled(_items.length, 0, growable: true);
{
final toDo = new Queue();
toDo.addAll(_items);
while (toDo.isNotEmpty) {
final item = toDo.removeFirst();
items.add(item);
if (isExpanded(item)) {
final children = _children(item);
children
.toList(growable: false)
.reversed
.forEach((c) => toDo.addFirst(c));
final depth = depths[items.length - 1];
depths.insertAll(
items.length, new List.filled(children.length, depth + 1));
}
}
}
_depths = depths;
_collection.items = items;
_r.waitFor([_collection.onRendered.first]);
}
}

View file

@ -1,143 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class ContextRefElement extends CustomElement implements Renderable {
RenderingScheduler<ContextRefElement> _r;
Stream<RenderedEvent<ContextRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.ContextRef _context;
M.ObjectRepository _objects;
M.Context _loadedContext;
bool _expandable;
bool _expanded = false;
M.IsolateRef get isolate => _isolate;
M.ContextRef get context => _context;
factory ContextRefElement(
M.IsolateRef isolate, M.ContextRef context, M.ObjectRepository objects,
{RenderingQueue queue, bool expandable = true}) {
assert(isolate != null);
assert(context != null);
assert(objects != null);
ContextRefElement e = new ContextRefElement.created();
e._r = new RenderingScheduler<ContextRefElement>(e, queue: queue);
e._isolate = isolate;
e._context = context;
e._objects = objects;
e._expandable = expandable;
return e;
}
ContextRefElement.created() : super.created('context-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
Future _refresh() async {
_loadedContext = await _objects.get(_isolate, _context.id);
_r.dirty();
}
void render() {
var children = <HtmlElement>[
new AnchorElement(href: Uris.inspect(_isolate, object: _context))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = 'Context',
new SpanElement()..text = ' (${_context.length})',
],
];
if (_expandable) {
children.addAll([
new SpanElement()..text = ' ',
(new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['indent']
..children = _createValue()
]
..onToggle.listen((e) async {
_expanded = e.control.expanded;
if (_expanded) {
e.control.disabled = true;
await _refresh();
e.control.disabled = false;
}
}))
.element
]);
}
this.children = children;
}
List<Element> _createValue() {
if (_loadedContext == null) {
return [new SpanElement()..text = 'Loading...'];
}
var members = <Element>[];
if (_loadedContext.parentContext != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'parent context',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new ContextRefElement(
_isolate, _loadedContext.parentContext, _objects,
queue: _r.queue)
.element
]
]);
}
if (_loadedContext.variables.isNotEmpty) {
var variables = _loadedContext.variables.toList();
for (var index = 0; index < variables.length; index++) {
var variable = variables[index];
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = '[ $index ]',
new DivElement()
..classes = ['memberName']
..children = <Element>[
anyRef(_isolate, variable.value, _objects, queue: _r.queue)
]
]);
}
}
return [
new DivElement()
..classes = ['memberList']
..children = members
];
}
}

View file

@ -1,191 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/context_ref.dart';
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/class_menu.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
class ContextViewElement extends CustomElement implements Renderable {
RenderingScheduler<ContextViewElement> _r;
Stream<RenderedEvent<ContextViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Context _context;
M.ContextRepository _contexts;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ObjectRepository _objects;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Context get context => _context;
factory ContextViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Context context,
M.EventRepository events,
M.NotificationRepository notifications,
M.ContextRepository contexts,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(context != null);
assert(contexts != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(objects != null);
ContextViewElement e = new ContextViewElement.created();
e._r = new RenderingScheduler<ContextViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._context = context;
e._contexts = contexts;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._objects = objects;
return e;
}
ContextViewElement.created() : super.created('context-view');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
var content = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
new NavClassMenuElement(_isolate, _context.clazz, queue: _r.queue)
.element,
navMenu('instance'),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_context = await _contexts.get(_isolate, _context.id);
_r.dirty();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Context',
new HRElement(),
new ObjectCommonElement(_isolate, _context, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element
]
];
if (_context.parentContext != null) {
content.addAll([
new BRElement(),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'parent context',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new ContextRefElement(
_isolate, _context.parentContext, _objects,
queue: _r.queue)
.element
]
]
]
]
]);
}
content.add(new HRElement());
if (_context.variables.isNotEmpty) {
int index = 0;
content.addAll([
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new SpanElement()..text = 'Variables ',
(new CurlyBlockElement(expanded: true, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = _context.variables
.map<Element>((variable) => new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = '[ ${++index} ]',
new DivElement()
..classes = ['memberName']
..children = <Element>[
anyRef(_isolate, variable.value, _objects,
queue: _r.queue)
]
])
.toList()
])
.element
]
]);
}
children = content;
}
}

View file

@ -1,169 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library cpu_profile_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/sample_buffer_control.dart';
import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
class CpuProfileElement extends CustomElement implements Renderable {
RenderingScheduler<CpuProfileElement> _r;
Stream<RenderedEvent<CpuProfileElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.IsolateSampleProfileRepository _profiles;
Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
M.SampleProfileLoadingProgress _progress;
M.SampleProfileTag _tag = M.SampleProfileTag.none;
ProfileTreeMode _mode = ProfileTreeMode.function;
M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
String _filter = '';
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.IsolateSampleProfileRepository get profiles => _profiles;
M.VMRef get vm => _vm;
factory CpuProfileElement(
M.VM vm,
M.IsolateRef isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.IsolateSampleProfileRepository profiles,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(profiles != null);
CpuProfileElement e = new CpuProfileElement.created();
e._r = new RenderingScheduler<CpuProfileElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._profiles = profiles;
return e;
}
CpuProfileElement.created() : super.created('cpu-profile');
@override
attached() {
super.attached();
_r.enable();
_request();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
var content = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('cpu profile', link: Uris.cpuProfiler(_isolate)),
(new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
.element,
(new NavRefreshElement(label: 'Clear', queue: _r.queue)
..onRefresh.listen(_clearCpuProfile))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
];
if (_progress == null) {
children = content;
return;
}
content.add((new SampleBufferControlElement(_vm, _progress, _progressStream,
selectedTag: _tag, queue: _r.queue)
..onTagChange.listen((e) {
_tag = e.element.selectedTag;
_request();
}))
.element);
if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
CpuProfileVirtualTreeElement tree;
content.addAll([
new BRElement(),
(new StackTraceTreeConfigElement(
mode: _mode,
direction: _direction,
filter: _filter,
queue: _r.queue)
..onModeChange.listen((e) {
_mode = tree.mode = e.element.mode;
})
..onFilterChange.listen((e) {
_filter = e.element.filter.trim();
tree.filters = _filter.isNotEmpty
? [
(node) {
return node.name.contains(_filter);
}
]
: const [];
})
..onDirectionChange.listen((e) {
_direction = tree.direction = e.element.direction;
}))
.element,
new BRElement(),
(tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
queue: _r.queue))
.element
]);
}
children = content;
}
Future _request({bool clear = false, bool forceFetch = false}) async {
_progress = null;
_progressStream =
_profiles.get(isolate, _tag, clear: clear, forceFetch: forceFetch);
_r.dirty();
_progress = (await _progressStream.first).progress;
_r.dirty();
if (M.isSampleProcessRunning(_progress.status)) {
_progress = (await _progressStream.last).progress;
_r.dirty();
}
}
Future _clearCpuProfile(RefreshEvent e) async {
e.element.disabled = true;
await _request(clear: true);
e.element.disabled = false;
}
Future _refresh(e) async {
e.element.disabled = true;
await _request(forceFetch: true);
e.element.disabled = false;
}
}

View file

@ -1,308 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'dart:math' as Math;
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/stack_trace_tree_config.dart'
show ProfileTreeMode;
import 'package:observatory_2/src/elements/code_ref.dart';
import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/utils.dart';
export 'package:observatory_2/src/elements/stack_trace_tree_config.dart'
show ProfileTreeMode;
class CpuProfileVirtualTreeElement extends CustomElement implements Renderable {
RenderingScheduler<CpuProfileVirtualTreeElement> _r;
Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
_r.onRendered;
M.ProfileTreeDirection _direction;
ProfileTreeMode _mode;
M.SampleProfileType _type;
M.IsolateRef _isolate;
M.SampleProfile _profile;
Iterable<M.CallTreeNodeFilter> _filters;
M.ProfileTreeDirection get direction => _direction;
ProfileTreeMode get mode => _mode;
M.SampleProfileType get type => _type;
M.IsolateRef get isolate => _isolate;
M.SampleProfile get profile => _profile;
Iterable<M.CallTreeNodeFilter> get filters => _filters;
set direction(M.ProfileTreeDirection value) =>
_direction = _r.checkAndReact(_direction, value);
set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
set filters(Iterable<M.CallTreeNodeFilter> value) {
_filters = new List.unmodifiable(value);
_r.dirty();
}
factory CpuProfileVirtualTreeElement(Object owner, M.SampleProfile profile,
{ProfileTreeMode mode = ProfileTreeMode.function,
M.SampleProfileType type = M.SampleProfileType.cpu,
M.ProfileTreeDirection direction = M.ProfileTreeDirection.exclusive,
RenderingQueue queue}) {
assert(profile != null);
assert(mode != null);
assert(direction != null);
CpuProfileVirtualTreeElement e = new CpuProfileVirtualTreeElement.created();
e._r =
new RenderingScheduler<CpuProfileVirtualTreeElement>(e, queue: queue);
e._isolate = owner;
e._profile = profile;
e._mode = mode;
e._type = type;
e._direction = direction;
return e;
}
CpuProfileVirtualTreeElement.created()
: super.created('cpu-profile-virtual-tree');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
VirtualTreeElement _tree;
void render() {
var tree;
var create;
var update;
var search;
switch (type) {
case M.SampleProfileType.cpu:
create = _createCpuRow;
if (mode == ProfileTreeMode.code) {
update = _updateCpuCodeRow;
search = _searchCode;
tree = _profile.loadCodeTree(_direction);
} else if (mode == ProfileTreeMode.function) {
update = _updateCpuFunctionRow;
search = _searchFunction;
tree = _profile.loadFunctionTree(_direction);
} else {
throw new Exception('Unknown ProfileTreeMode: $mode');
}
break;
case M.SampleProfileType.memory:
create = _createMemoryRow;
if (mode == ProfileTreeMode.code) {
update = _updateMemoryCodeRow;
search = _searchCode;
tree = _profile.loadCodeTree(_direction);
} else if (mode == ProfileTreeMode.function) {
update = _updateMemoryFunctionRow;
search = _searchFunction;
tree = _profile.loadFunctionTree(_direction);
} else {
throw new Exception('Unknown ProfileTreeMode: $mode');
}
break;
default:
throw new Exception('Unknown SampleProfileType: $type');
}
if (filters != null) {
tree = filters.fold(tree, (tree, filter) {
return tree?.filtered(filter);
});
}
if (tree == null) {
children = <Element>[new HeadingElement.h1()..text = 'No Results'];
return;
}
_tree = new VirtualTreeElement(create, update, _getChildren,
items: tree.root.children, search: search, queue: _r.queue);
if (tree.root.children.length == 0) {
children = <Element>[
new DivElement()
..classes = ['tree-item']
..children = <Element>[new HeadingElement.h1()..text = 'No Samples']
];
return;
} else if (tree.root.children.length == 1) {
_tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
}
children = <Element>[_tree.element];
}
static HtmlElement _createCpuRow(toggle) {
return new DivElement()
..classes = ['tree-item']
..children = <Element>[
new SpanElement()
..classes = ['inclusive']
..title = 'global % on stack',
new SpanElement()
..classes = ['exclusive']
..title = 'global % executing',
new SpanElement()..classes = ['lines'],
new ButtonElement()
..classes = ['expander']
..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
new SpanElement()
..classes = ['percentage']
..title = 'tree node %',
new SpanElement()..classes = ['name']
];
}
static HtmlElement _createMemoryRow(toggle) {
return new DivElement()
..classes = ['tree-item']
..children = <Element>[
new SpanElement()
..classes = ['inclusive']
..title = 'memory allocated from resulting calls: ',
new SpanElement()
..classes = ['exclusive']
..title = 'memory allocated during execution: ',
new SpanElement()..classes = ['lines'],
new ButtonElement()
..classes = ['expander']
..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
new SpanElement()
..classes = ['percentage']
..title = 'tree node %',
new SpanElement()..classes = ['name']
];
}
static Iterable<M.CallTreeNode> _getChildren(nodeDynamic) {
M.CallTreeNode node = nodeDynamic;
return node.children;
}
static const String _expandedIcon = '';
static const String _collapsedIcon = '';
void _updateCpuFunctionRow(HtmlElement element, itemDynamic, int depth) {
M.FunctionCallTreeNode item = itemDynamic;
element.children[0].text = Utils.formatPercentNormalized(
item.profileFunction.normalizedInclusiveTicks);
element.children[1].text = Utils.formatPercentNormalized(
item.profileFunction.normalizedExclusiveTicks);
_updateLines(element.children[2].children, depth);
if (item.children.isNotEmpty) {
element.children[3].text =
_tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
} else {
element.children[3].text = '';
}
element.children[4].text = Utils.formatPercentNormalized(item.percentage);
element.children[5] = (new FunctionRefElement(
_isolate, item.profileFunction.function,
queue: _r.queue)
..classes = ['name'])
.element;
}
void _updateMemoryFunctionRow(HtmlElement element, itemDynamic, int depth) {
M.FunctionCallTreeNode item = itemDynamic;
element.children[0].text =
Utils.formatSize(item.inclusiveNativeAllocations);
element.children[0].title = 'memory allocated from resulting calls: '
'${item.inclusiveNativeAllocations}B';
element.children[1].text =
Utils.formatSize(item.exclusiveNativeAllocations);
element.children[1].title = 'memory allocated during execution: '
'${item.exclusiveNativeAllocations}B';
_updateLines(element.children[2].children, depth);
if (item.children.isNotEmpty) {
element.children[3].text =
_tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
} else {
element.children[3].text = '';
}
element.children[4].text = Utils.formatPercentNormalized(item.percentage);
element.children[5] = (new FunctionRefElement(
null, item.profileFunction.function,
queue: _r.queue)
..classes = ['name'])
.element;
}
bool _searchFunction(Pattern pattern, itemDynamic) {
M.FunctionCallTreeNode item = itemDynamic;
return M
.getFunctionFullName(item.profileFunction.function)
.contains(pattern);
}
void _updateCpuCodeRow(HtmlElement element, itemDynamic, int depth) {
M.CodeCallTreeNode item = itemDynamic;
element.children[0].text = Utils.formatPercentNormalized(
item.profileCode.normalizedInclusiveTicks);
element.children[1].text = Utils.formatPercentNormalized(
item.profileCode.normalizedExclusiveTicks);
_updateLines(element.children[2].children, depth);
if (item.children.isNotEmpty) {
element.children[3].text =
_tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
} else {
element.children[3].text = '';
}
element.children[4].text = Utils.formatPercentNormalized(item.percentage);
element.children[5] =
(new CodeRefElement(_isolate, item.profileCode.code, queue: _r.queue)
..classes = ['name'])
.element;
}
void _updateMemoryCodeRow(HtmlElement element, itemDynamic, int depth) {
M.CodeCallTreeNode item = itemDynamic;
element.children[0].text =
Utils.formatSize(item.inclusiveNativeAllocations);
element.children[0].title = 'memory allocated from resulting calls: '
'${item.inclusiveNativeAllocations}B';
element.children[1].text =
Utils.formatSize(item.exclusiveNativeAllocations);
element.children[1].title = 'memory allocated during execution: '
'${item.exclusiveNativeAllocations}B';
_updateLines(element.children[2].children, depth);
if (item.children.isNotEmpty) {
element.children[3].text =
_tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
} else {
element.children[3].text = '';
}
element.children[4].text = Utils.formatPercentNormalized(item.percentage);
element.children[5] =
(new CodeRefElement(null, item.profileCode.code, queue: _r.queue)
..classes = ['name'])
.element;
}
bool _searchCode(Pattern pattern, itemDynamic) {
M.CodeCallTreeNode item = itemDynamic;
return item.profileCode.code.name.contains(pattern);
}
static _updateLines(List<Element> lines, int n) {
n = Math.max(0, n);
while (lines.length > n) {
lines.removeLast();
}
while (lines.length < n) {
lines.add(new SpanElement());
}
}
}

View file

@ -1,473 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library cpu_profile_table_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/sample_buffer_control.dart';
import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
import 'package:observatory_2/utils.dart';
enum _Table { functions, caller, callee }
enum _SortingField { exclusive, inclusive, caller, callee, method }
enum _SortingDirection { ascending, descending }
class CpuProfileTableElement extends CustomElement implements Renderable {
RenderingScheduler<CpuProfileTableElement> _r;
Stream<RenderedEvent<CpuProfileTableElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.IsolateSampleProfileRepository _profiles;
Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
M.SampleProfileLoadingProgress _progress;
final _sortingField = <_Table, _SortingField>{
_Table.functions: _SortingField.exclusive,
_Table.caller: _SortingField.caller,
_Table.callee: _SortingField.callee,
};
final _sortingDirection = <_Table, _SortingDirection>{
_Table.functions: _SortingDirection.descending,
_Table.caller: _SortingDirection.descending,
_Table.callee: _SortingDirection.descending,
};
String _filter = '';
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.IsolateSampleProfileRepository get profiles => _profiles;
M.VMRef get vm => _vm;
factory CpuProfileTableElement(
M.VM vm,
M.IsolateRef isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.IsolateSampleProfileRepository profiles,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(profiles != null);
CpuProfileTableElement e = new CpuProfileTableElement.created();
e._r = new RenderingScheduler<CpuProfileTableElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._profiles = profiles;
return e;
}
CpuProfileTableElement.created() : super.created('cpu-profile-table');
@override
attached() {
super.attached();
_r.enable();
_request();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
var content = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('cpu profile (table)'),
(new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
.element,
(new NavRefreshElement(label: 'Clear', queue: _r.queue)
..onRefresh.listen(_clearCpuSamples))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
];
if (_progress == null) {
children = content;
return;
}
content.add(new SampleBufferControlElement(_vm, _progress, _progressStream,
showTag: false, queue: _r.queue)
.element);
if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
content.add(new BRElement());
content.addAll(_createTables());
content.add(new BRElement());
content.addAll(_createTree());
}
children = content;
}
M.ProfileFunction _selected;
VirtualCollectionElement _functions;
VirtualCollectionElement _callers;
VirtualCollectionElement _callees;
List<Element> _createTables() {
_functions = _functions ??
new VirtualCollectionElement(_createFunction, _updateFunction,
createHeader: _createFunctionHeader,
search: _searchFunction,
queue: _r.queue);
// If there's no samples, don't populate the function list.
_functions.items = (_progress.profile.sampleCount != 0)
? _progress.profile.functions.toList()
: []
..sort(_createSorter(_Table.functions));
_functions.takeIntoView(_selected);
_callers = _callers ??
new VirtualCollectionElement(_createCaller, _updateCaller,
createHeader: _createCallerHeader,
search: _searchFunction,
queue: _r.queue);
_callees = _callees ??
new VirtualCollectionElement(_createCallee, _updateCallee,
createHeader: _createCalleeHeader,
search: _searchFunction,
queue: _r.queue);
if (_selected != null) {
_callers.items = _selected.callers.keys.toList()
..sort(_createSorter(_Table.caller));
_callees.items = _selected.callees.keys.toList()
..sort(_createSorter(_Table.callee));
} else {
_callers.items = const [];
_callees.items = const [];
}
return <Element>[
new DivElement()
..classes = ['profile-trees']
..children = <Element>[
new DivElement()
..classes = ['profile-trees-all']
..children = <Element>[_functions.element],
new DivElement()
..classes = ['profile-trees-current']
..children = <Element>[
new DivElement()
..classes = ['profile-trees-caller']
..children = <Element>[_callers.element],
new DivElement()
..classes = ['profile-trees-selected']
..children = _selected == null
? [new SpanElement()..text = 'No element selected']
: [
new FunctionRefElement(_isolate, _selected.function,
queue: _r.queue)
.element
],
new DivElement()
..classes = ['profile-trees-callee']
..children = <Element>[_callees.element]
]
]
];
}
HtmlElement _createFunction() {
final element = new DivElement()
..classes = ['function-item']
..children = <Element>[
new SpanElement()
..classes = ['exclusive']
..text = '0%',
new SpanElement()
..classes = ['inclusive']
..text = '0%',
new SpanElement()..classes = ['name']
];
element.onClick.listen((e) {
if (e.target is AnchorElement) {
return;
}
_selected = _functions.getItemFromElement(element);
_r.dirty();
});
return element;
}
void _updateFunction(Element e, itemDynamic, int index) {
M.ProfileFunction item = itemDynamic;
if (item == _selected) {
e.classes = ['function-item', 'selected'];
} else {
e.classes = ['function-item'];
}
e.children[0].text = Utils.formatPercentNormalized(_getExclusiveT(item));
e.children[1].text = Utils.formatPercentNormalized(_getInclusiveT(item));
e.children[2].text = M.getFunctionFullName(item.function);
}
List<HtmlElement> _createFunctionHeader() => [
new DivElement()
..classes = ['function-item']
..children = <Element>[
_createHeaderButton(
const ['exclusive'],
'Execution(%)',
_Table.functions,
_SortingField.exclusive,
_SortingDirection.descending),
_createHeaderButton(
const ['inclusive'],
'Stack(%)',
_Table.functions,
_SortingField.inclusive,
_SortingDirection.descending),
_createHeaderButton(const ['name'], 'Method', _Table.functions,
_SortingField.method, _SortingDirection.ascending),
]
];
bool _searchFunction(Pattern pattern, itemDynamic) {
M.ProfileFunction item = itemDynamic;
return M.getFunctionFullName(item.function).contains(pattern);
}
void _setSorting(
_Table table, _SortingField field, _SortingDirection defaultDirection) {
if (_sortingField[table] == field) {
switch (_sortingDirection[table]) {
case _SortingDirection.descending:
_sortingDirection[table] = _SortingDirection.ascending;
break;
case _SortingDirection.ascending:
_sortingDirection[table] = _SortingDirection.descending;
break;
}
} else {
_sortingDirection[table] = defaultDirection;
_sortingField[table] = field;
}
_r.dirty();
}
HtmlElement _createCallee() {
final element = new DivElement()
..classes = ['function-item']
..children = <Element>[
new SpanElement()
..classes = ['inclusive']
..text = '0%',
new SpanElement()..classes = ['name']
];
element.onClick.listen((e) {
if (e.target is AnchorElement) {
return;
}
_selected = _callees.getItemFromElement(element);
_r.dirty();
});
return element;
}
void _updateCallee(Element e, item, int index) {
e.children[0].text = Utils.formatPercentNormalized(_getCalleeT(item));
e.children[1].text = M.getFunctionFullName(item.function);
}
List<HtmlElement> _createCalleeHeader() => [
new DivElement()
..classes = ['function-item']
..children = <Element>[
_createHeaderButton(
const ['inclusive'],
'Callees(%)',
_Table.callee,
_SortingField.callee,
_SortingDirection.descending),
_createHeaderButton(const ['name'], 'Method', _Table.callee,
_SortingField.method, _SortingDirection.ascending),
]
];
HtmlElement _createCaller() {
final element = new DivElement()
..classes = ['function-item']
..children = <Element>[
new SpanElement()
..classes = ['inclusive']
..text = '0%',
new SpanElement()..classes = ['name']
];
element.onClick.listen((e) {
if (e.target is AnchorElement) {
return;
}
_selected = _callers.getItemFromElement(element);
_r.dirty();
});
return element;
}
void _updateCaller(Element e, item, int index) {
e.children[0].text = Utils.formatPercentNormalized(_getCallerT(item));
e.children[1].text = M.getFunctionFullName(item.function);
}
List<HtmlElement> _createCallerHeader() => [
new DivElement()
..classes = ['function-item']
..children = <Element>[
_createHeaderButton(
const ['inclusive'],
'Callers(%)',
_Table.caller,
_SortingField.caller,
_SortingDirection.descending),
_createHeaderButton(const ['name'], 'Method', _Table.caller,
_SortingField.method, _SortingDirection.ascending),
]
];
ButtonElement _createHeaderButton(List<String> classes, String text,
_Table table, _SortingField field, _SortingDirection direction) =>
new ButtonElement()
..classes = classes
..text = _sortingField[table] != field
? text
: _sortingDirection[table] == _SortingDirection.ascending
? '$text'
: '$text'
..onClick.listen((_) => _setSorting(table, field, direction));
List<Element> _createTree() {
CpuProfileVirtualTreeElement tree;
return [
(new StackTraceTreeConfigElement(
showMode: false,
showDirection: false,
mode: ProfileTreeMode.function,
direction: M.ProfileTreeDirection.exclusive,
filter: _filter,
queue: _r.queue)
..onFilterChange.listen((e) {
_filter = e.element.filter.trim();
tree.filters = _filter.isNotEmpty
? [
_filterTree,
(node) {
return node.name.contains(_filter);
}
]
: [_filterTree];
}))
.element,
new BRElement(),
(tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
mode: ProfileTreeMode.function,
direction: M.ProfileTreeDirection.exclusive,
queue: _r.queue)
..filters = _filter.isNotEmpty
? [
_filterTree,
(node) {
return node.name.contains(_filter);
}
]
: [_filterTree])
.element
];
}
bool _filterTree(nodeDynamic) {
M.FunctionCallTreeNode node = nodeDynamic;
return node.profileFunction == _selected;
}
Future _request({bool clear = false, bool forceFetch = false}) async {
_progress = null;
_progressStream = _profiles.get(isolate, M.SampleProfileTag.vmOnly,
clear: clear, forceFetch: forceFetch);
_r.dirty();
_progress = (await _progressStream.first).progress;
_r.dirty();
if (M.isSampleProcessRunning(_progress.status)) {
_progress = (await _progressStream.last).progress;
_r.dirty();
}
}
Future _clearCpuSamples(RefreshEvent e) async {
e.element.disabled = true;
await _request(clear: true);
e.element.disabled = false;
}
Future _refresh(e) async {
e.element.disabled = true;
await _request(forceFetch: true);
e.element.disabled = false;
}
_createSorter(_Table table) {
var getter;
switch (_sortingField[table]) {
case _SortingField.exclusive:
getter = _getExclusiveT;
break;
case _SortingField.inclusive:
getter = _getInclusiveT;
break;
case _SortingField.callee:
getter = _getCalleeT;
break;
case _SortingField.caller:
getter = _getCallerT;
break;
case _SortingField.method:
getter = (M.ProfileFunction s) => M.getFunctionFullName(s.function);
break;
}
switch (_sortingDirection[table]) {
case _SortingDirection.ascending:
int sort(a, b) {
return getter(a).compareTo(getter(b));
}
return sort;
case _SortingDirection.descending:
int sort(a, b) {
return getter(b).compareTo(getter(a));
}
return sort;
}
}
static double _getExclusiveT(M.ProfileFunction f) =>
f.normalizedExclusiveTicks;
static double _getInclusiveT(M.ProfileFunction f) =>
f.normalizedInclusiveTicks;
double _getCalleeT(M.ProfileFunction f) =>
_selected.callees[f] / _selected.callees.values.reduce((a, b) => a + b);
double _getCallerT(M.ProfileFunction f) =>
_selected.callers[f] / _selected.callers.values.reduce((a, b) => a + b);
}

File diff suppressed because it is too large Load diff

View file

@ -1,102 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library curly_block_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
class CurlyBlockToggleEvent {
final CurlyBlockElement control;
CurlyBlockToggleEvent(this.control);
}
class CurlyBlockElement extends CustomElement implements Renderable {
RenderingScheduler<CurlyBlockElement> _r;
final StreamController<CurlyBlockToggleEvent> _onToggle =
new StreamController<CurlyBlockToggleEvent>.broadcast();
Stream<CurlyBlockToggleEvent> get onToggle => _onToggle.stream;
Stream<RenderedEvent<CurlyBlockElement>> get onRendered => _r.onRendered;
bool _expanded;
bool _disabled;
Iterable<Element> _content = const [];
bool get expanded => _expanded;
bool get disabled => _disabled;
Iterable<Element> get content => _content;
set expanded(bool value) {
if (_expanded != value) _onToggle.add(new CurlyBlockToggleEvent(this));
_expanded = _r.checkAndReact(_expanded, value);
}
set disabled(bool value) => _disabled = _r.checkAndReact(_disabled, value);
set content(Iterable<Element> value) {
_content = value.toList();
_r.dirty();
}
factory CurlyBlockElement(
{bool expanded = false, bool disabled = false, RenderingQueue queue}) {
assert(expanded != null);
assert(disabled != null);
CurlyBlockElement e = new CurlyBlockElement.created();
e._r = new RenderingScheduler<CurlyBlockElement>(e, queue: queue);
e._expanded = expanded;
e._disabled = disabled;
return e;
}
CurlyBlockElement.created() : super.created('curly-block');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void toggle() {
if (disabled) {
_r.scheduleNotification();
return;
}
expanded = !expanded;
}
void render() {
List<Element> content = <Element>[new SpanElement()..text = '{'];
SpanElement label = new SpanElement()
..classes = disabled ? ['curly-block', 'disabled'] : ['curly-block']
..innerHtml = expanded
? '&nbsp;&nbsp;&#8863;&nbsp;&nbsp;'
: '&nbsp;&nbsp;&#8862;&nbsp;&nbsp;';
if (disabled) {
content.add(label);
} else {
content.add(new AnchorElement()
..onClick.listen((_) {
toggle();
})
..children = <Element>[label]);
}
if (expanded) {
content.add(new BRElement());
content.addAll(_content);
}
content.add(new SpanElement()..text = '}');
children = content;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,48 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library error_ref_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' show ErrorRef;
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
class ErrorRefElement extends CustomElement implements Renderable {
RenderingScheduler<ErrorRefElement> _r;
Stream<RenderedEvent<ErrorRefElement>> get onRendered => _r.onRendered;
ErrorRef _error;
ErrorRef get error => _error;
factory ErrorRefElement(ErrorRef error, {RenderingQueue queue}) {
assert(error != null);
ErrorRefElement e = new ErrorRefElement.created();
e._r = new RenderingScheduler<ErrorRefElement>(e, queue: queue);
e._error = error;
return e;
}
ErrorRefElement.created() : super.created('error-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
children = <Element>[new PreElement()..text = error.message];
}
}

View file

@ -1,85 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library error_view_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
class ErrorViewElement extends CustomElement implements Renderable {
RenderingScheduler<ErrorViewElement> _r;
Stream<RenderedEvent<ErrorViewElement>> get onRendered => _r.onRendered;
M.Error _error;
M.NotificationRepository _notifications;
M.Error get error => _error;
factory ErrorViewElement(
M.NotificationRepository notifications, M.Error error,
{RenderingQueue queue}) {
assert(error != null);
assert(notifications != null);
ErrorViewElement e = new ErrorViewElement.created();
e._r = new RenderingScheduler<ErrorViewElement>(e, queue: queue);
e._error = error;
e._notifications = notifications;
return e;
}
ErrorViewElement.created() : super.created('error-view');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered']
..children = <Element>[
new HeadingElement.h1()
..text = 'Error: ${_kindToString(_error.kind)}',
new BRElement(),
new DivElement()
..classes = ['well']
..children = <Element>[new PreElement()..text = error.message]
],
];
}
static String _kindToString(M.ErrorKind kind) {
switch (kind) {
case M.ErrorKind.unhandledException:
return 'Unhandled Exception';
case M.ErrorKind.languageError:
return 'Language Error';
case M.ErrorKind.internalError:
return 'Internal Error';
case M.ErrorKind.terminationError:
return 'Termination Error';
}
throw new Exception('Unknown M.ErrorKind ($kind)');
}
}

View file

@ -1,206 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library eval_box_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class EvalBoxElement extends CustomElement implements Renderable {
RenderingScheduler<EvalBoxElement> _r;
Stream<RenderedEvent<EvalBoxElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.ObjectRef _context;
M.ObjectRepository _objects;
M.EvalRepository _eval;
final _results = <_ExpressionDescription>[];
String _expression = '';
bool _multiline;
Iterable<String> _quickExpressions;
M.IsolateRef get isolate => _isolate;
M.ObjectRef get context => _context;
factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context,
M.ObjectRepository objects, M.EvalRepository eval,
{bool multiline = false,
Iterable<String> quickExpressions = const [],
RenderingQueue queue}) {
assert(isolate != null);
assert(context != null);
assert(objects != null);
assert(eval != null);
assert(multiline != null);
assert(quickExpressions != null);
EvalBoxElement e = new EvalBoxElement.created();
e._r = new RenderingScheduler<EvalBoxElement>(e, queue: queue);
e._isolate = isolate;
e._context = context;
e._objects = objects;
e._eval = eval;
e._multiline = multiline;
e._quickExpressions = new List.unmodifiable(quickExpressions);
return e;
}
EvalBoxElement.created() : super.created('eval-box');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_results.clear();
}
void render() {
children = <Element>[
new DivElement()
..classes = ['quicks']
..children = _quickExpressions
.map<Element>((q) => new ButtonElement()
..text = q
..onClick.listen((_) {
_expression = q;
_run();
}))
.toList(),
new DivElement()
..classes = ['heading']
..children = <Element>[
new FormElement()
..autocomplete = 'on'
..children = <Element>[
_multiline ? _createEvalTextArea() : _createEvalTextBox(),
new SpanElement()
..classes = ['buttons']
..children = <Element>[
_createEvalButton(),
_createMultilineCheckbox(),
new SpanElement()..text = 'Multi-line'
]
]
],
new TableElement()
..children = _results.reversed
.map<Element>((result) => new TableRowElement()
..children = <Element>[
new TableCellElement()
..classes = ['historyExpr']
..children = <Element>[
new ButtonElement()
..text = result.expression
..onClick.listen((_) {
_expression = result.expression;
_r.dirty();
})
],
new TableCellElement()
..classes = ['historyValue']
..children = <Element>[
result.isPending
? (new SpanElement()..text = 'Pending...')
: anyRef(_isolate, result.value, _objects,
queue: _r.queue)
],
new TableCellElement()
..classes = ['historyDelete']
..children = <Element>[
new ButtonElement()
..text = '✖ Remove'
..onClick.listen((_) {
_results.remove(result);
_r.dirty();
})
]
])
.toList()
];
}
TextAreaElement _createEvalTextArea() {
var area = new TextAreaElement()
..classes = ['textbox']
..placeholder = 'evaluate an expression'
..value = _expression
..onKeyUp.where((e) => e.key == '\n').listen((e) {
e.preventDefault();
_run();
});
area.onInput.listen((e) {
_expression = area.value;
});
return area;
}
TextInputElement _createEvalTextBox() {
_expression = (_expression ?? '').split('\n')[0];
var textbox = new TextInputElement()
..classes = ['textbox']
..placeholder = 'evaluate an expression'
..value = _expression
..onKeyUp.where((e) => e.key == '\n').listen((e) {
e.preventDefault();
_run();
});
textbox.onInput.listen((e) {
_expression = textbox.value;
});
return textbox;
}
ButtonElement _createEvalButton() {
final button = new ButtonElement()
..text = 'Evaluate'
..onClick.listen((e) {
e.preventDefault();
_run();
});
return button;
}
CheckboxInputElement _createMultilineCheckbox() {
final checkbox = new CheckboxInputElement()..checked = _multiline;
checkbox.onClick.listen((e) {
e.preventDefault();
_multiline = checkbox.checked;
_r.dirty();
});
return checkbox;
}
Future _run() async {
if (_expression == null || _expression.isEmpty) return;
final expression = _expression;
_expression = null;
final result = new _ExpressionDescription.pending(expression);
_results.add(result);
_r.dirty();
final index = _results.indexOf(result);
_results[index] = new _ExpressionDescription(
expression, await _eval.evaluate(_isolate, _context, expression));
_r.dirty();
}
}
class _ExpressionDescription {
final String expression;
final M.ObjectRef value;
bool get isPending => value == null;
_ExpressionDescription(this.expression, this.value);
_ExpressionDescription.pending(this.expression) : value = null;
}

View file

@ -1,90 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
class FieldRefElement extends CustomElement implements Renderable {
RenderingScheduler<FieldRefElement> _r;
Stream<RenderedEvent<FieldRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.FieldRef _field;
M.ObjectRepository _objects;
bool _expandable;
M.IsolateRef get isolate => _isolate;
M.FieldRef get field => _field;
factory FieldRefElement(
M.IsolateRef isolate, M.FieldRef field, M.ObjectRepository objects,
{RenderingQueue queue, bool expandable = true}) {
assert(isolate != null);
assert(field != null);
assert(objects != null);
FieldRefElement e = new FieldRefElement.created();
e._r = new RenderingScheduler<FieldRefElement>(e, queue: queue);
e._isolate = isolate;
e._field = field;
e._objects = objects;
e._expandable = expandable;
return e;
}
FieldRefElement.created() : super.created('field-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
var header = '';
if (_field.isStatic) {
if (_field.dartOwner is M.ClassRef) {
header += 'static ';
} else {
header += 'top-level ';
}
}
if (_field.isFinal) {
header += 'final ';
} else if (_field.isConst) {
header += 'const ';
} else if (_field.declaredType.name == 'dynamic') {
header += 'var ';
}
if (_field.declaredType.name == 'dynamic') {
children = <Element>[
new SpanElement()..text = header,
new AnchorElement(href: Uris.inspect(_isolate, object: _field))
..text = _field.name
];
} else {
children = <Element>[
new SpanElement()..text = header,
new InstanceRefElement(_isolate, _field.declaredType, _objects,
queue: _r.queue, expandable: _expandable)
.element,
new SpanElement()..text = ' ',
new AnchorElement(href: Uris.inspect(_isolate, object: _field))
..text = _field.name
];
}
}
}

View file

@ -1,288 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library field_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/class_menu.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/library_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/script_inset.dart';
import 'package:observatory_2/src/elements/source_link.dart';
class FieldViewElement extends CustomElement implements Renderable {
RenderingScheduler<FieldViewElement> _r;
Stream<RenderedEvent<FieldViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Field _field;
M.LibraryRef _library;
M.FieldRepository _fields;
M.ClassRepository _classes;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ScriptRepository _scripts;
M.ObjectRepository _objects;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Field get field => _field;
factory FieldViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Field field,
M.EventRepository events,
M.NotificationRepository notifications,
M.FieldRepository fields,
M.ClassRepository classes,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ScriptRepository scripts,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(field != null);
assert(fields != null);
assert(classes != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(scripts != null);
assert(objects != null);
FieldViewElement e = new FieldViewElement.created();
e._r = new RenderingScheduler<FieldViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._field = field;
e._fields = fields;
e._classes = classes;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._scripts = scripts;
e._objects = objects;
if (field.dartOwner is M.LibraryRef) {
e._library = field.dartOwner;
}
return e;
}
FieldViewElement.created() : super.created('field-view');
@override
attached() {
super.attached();
_r.enable();
_refresh();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
var header = '';
if (_field.isStatic) {
if (_field.dartOwner is M.ClassRef) {
header += 'static ';
} else {
header += 'top-level ';
}
}
if (_field.isFinal) {
header += 'final ';
} else if (_field.isConst) {
header += 'const ';
}
if (_field.declaredType.name == 'dynamic') {
header += 'var';
} else {
header += _field.declaredType.name;
}
children = <Element>[
navBar(_createMenu()),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = '$header ${field.name}',
new HRElement(),
new ObjectCommonElement(_isolate, _field, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createMembers(),
new HRElement(),
new DivElement()
..children = _field.location == null
? const []
: [
new ScriptInsetElement(_isolate, _field.location.script,
_scripts, _objects, _events,
startPos: field.location.tokenPos,
endPos: field.location.tokenPos,
queue: _r.queue)
.element
],
]
];
}
List<Element> _createMenu() {
final menu = <Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
];
if (_library != null) {
menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
.element);
} else if (_field.dartOwner is M.ClassRef) {
menu.add(
new NavClassMenuElement(_isolate, _field.dartOwner, queue: _r.queue)
.element);
}
menu.addAll(<Element>[
navMenu(_field.name),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]);
return menu;
}
List<Element> _createMembers() {
final members = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'owner',
new DivElement()
..classes = ['memberName']
..children = <Element>[
_field.dartOwner == null
? (new SpanElement()..text = '...')
: anyRef(_isolate, _field.dartOwner, _objects,
queue: _r.queue)
]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'script',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new SourceLinkElement(_isolate, field.location, _scripts,
queue: _r.queue)
.element
]
]
];
if (!_field.isStatic) {
members.add(new DivElement()
..classes = ['memberItem']
..title = 'The types observed for this field at runtime. '
'Fields that are observed to have a single type at runtime '
'or to never be null may allow for additional optimization.'
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'observed types',
new DivElement()
..classes = ['memberName']
..children = _createGuard()
]);
}
if (_field.staticValue != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'static value',
new DivElement()
..classes = ['memberName']
..children = <Element>[
anyRef(_isolate, _field.staticValue, _objects, queue: _r.queue)
]
]);
}
return members;
}
List<Element> _createGuard() {
final guard = <Element>[];
switch (_field.guardClassKind) {
case M.GuardClassKind.unknown:
guard.add(new SpanElement()..text = 'none');
break;
case M.GuardClassKind.dynamic:
guard.add(new SpanElement()..text = 'various');
break;
case M.GuardClassKind.single:
guard.add(
new ClassRefElement(_isolate, _field.guardClass, queue: _r.queue)
.element);
break;
}
guard.add(new SpanElement()
..text =
_field.guardNullable ? '— null observed' : '— null not observed');
return guard;
}
Future _refresh() async {
_field = await _fields.get(_isolate, _field.id);
if (_field.dartOwner is M.LibraryRef) {
_library = _field.dartOwner;
} else if (_field.dartOwner is M.ClassRef) {
_library = (await _classes.get(_isolate, _field.dartOwner.id)).library;
}
_r.dirty();
}
}

View file

@ -1,143 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library flag_list_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
class FlagListElement extends CustomElement implements Renderable {
RenderingScheduler<FlagListElement> _r;
Stream<RenderedEvent<FlagListElement>> get onRendered => _r.onRendered;
M.VMRef _vm;
M.EventRepository _events;
M.FlagsRepository _repository;
M.NotificationRepository _notifications;
Iterable<M.Flag> _flags;
M.VMRef get vm => _vm;
factory FlagListElement(M.VMRef vm, M.EventRepository events,
M.FlagsRepository repository, M.NotificationRepository notifications,
{RenderingQueue queue}) {
assert(vm != null);
assert(events != null);
assert(repository != null);
assert(notifications != null);
FlagListElement e = new FlagListElement.created();
e._r = new RenderingScheduler<FlagListElement>(e, queue: queue);
e._vm = vm;
e._events = events;
e._repository = repository;
e._notifications = notifications;
return e;
}
FlagListElement.created() : super.created('flag-list');
@override
void attached() {
super.attached();
_refresh();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
final content = <Element>[];
if (_flags == null) {
content.add(new HeadingElement.h1()..text = 'Loading Flags...');
} else {
final modified = _flags.where(_isModified);
final unmodified = _flags.where(_isUnmodified);
if (modified.isNotEmpty) {
content.add(new HeadingElement.h1()..text = 'Modified Flags');
content.add(new BRElement());
content.addAll(modified.expand(_renderFlag));
content.add(new HRElement());
}
content.add(new HeadingElement.h1()..text = 'Unmodified Flags');
content.add(new BRElement());
if (unmodified.isEmpty) {
content.add(new HeadingElement.h2()..text = 'None');
} else {
content.addAll(unmodified.expand(_renderFlag));
}
}
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
navMenu('flags', link: Uris.flags()),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
try {
await _refresh();
} finally {
e.element.disabled = false;
}
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered']
..children = content,
];
}
Future _refresh() {
return _repository.list().then((flags) {
_flags = flags;
_r.dirty();
});
}
static bool _isModified(M.Flag flag) => flag.modified;
static bool _isUnmodified(M.Flag flag) => !flag.modified;
static List<Element> _renderFlag(M.Flag flag) {
return [
new SpanElement()
..classes = ['comment']
..text = '// ${flag.comment}',
new DivElement()
..classes =
flag.modified ? ['flag', 'modified'] : ['flag', 'unmodified']
..children = <Element>[
new SpanElement()
..classes = ['name']
..text = flag.name,
new SpanElement()..text = '=',
new SpanElement()
..classes = ['value']
..text = flag.valueAsString ?? 'NULL'
],
new BRElement(),
];
}
}

View file

@ -1,95 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library function_ref_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M
show
IsolateRef,
FunctionRef,
isSyntheticFunction,
ClassRef,
ObjectRef,
getFunctionFullName;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class FunctionRefElement extends CustomElement implements Renderable {
RenderingScheduler<FunctionRefElement> _r;
Stream<RenderedEvent<FunctionRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.FunctionRef _function;
bool _qualified;
M.IsolateRef get isolate => _isolate;
M.FunctionRef get function => _function;
bool get qualified => _qualified;
factory FunctionRefElement(M.IsolateRef isolate, M.FunctionRef function,
{bool qualified = true, RenderingQueue queue}) {
assert(function != null);
assert(qualified != null);
FunctionRefElement e = new FunctionRefElement.created();
e._r = new RenderingScheduler<FunctionRefElement>(e, queue: queue);
e._isolate = isolate;
e._function = function;
e._qualified = qualified;
return e;
}
FunctionRefElement.created() : super.created('function-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
title = '';
_r.disable(notify: true);
}
void render() {
var content = <Element>[
new AnchorElement(
href: (M.isSyntheticFunction(_function.kind) || (_isolate == null))
? null
: Uris.inspect(_isolate, object: _function))
..text = _function.name
];
if (qualified) {
M.ObjectRef owner = _function.dartOwner;
while (owner is M.FunctionRef) {
M.FunctionRef function = (owner as M.FunctionRef);
content.addAll([
new SpanElement()..text = '.',
new AnchorElement(
href: (M.isSyntheticFunction(function.kind) || (_isolate == null))
? null
: Uris.inspect(_isolate, object: function))
..text = function.name
]);
owner = function.dartOwner;
}
if (owner is M.ClassRef) {
content.addAll([
new SpanElement()..text = '.',
new ClassRefElement(_isolate, owner, queue: _r.queue).element
]);
}
}
children = content.reversed.toList(growable: false);
title = M.getFunctionFullName(_function);
}
}

View file

@ -1,426 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library function_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/code_ref.dart';
import 'package:observatory_2/src/elements/field_ref.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/class_menu.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/library_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/source_inset.dart';
import 'package:observatory_2/src/elements/source_link.dart';
class FunctionViewElement extends CustomElement implements Renderable {
RenderingScheduler<FunctionViewElement> _r;
Stream<RenderedEvent<FunctionViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.ServiceFunction _function;
M.LibraryRef _library;
M.FunctionRepository _functions;
M.ClassRepository _classes;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ScriptRepository _scripts;
M.ObjectRepository _objects;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.ServiceFunction get function => _function;
factory FunctionViewElement(
M.VM vm,
M.IsolateRef isolate,
M.ServiceFunction function,
M.EventRepository events,
M.NotificationRepository notifications,
M.FunctionRepository functions,
M.ClassRepository classes,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ScriptRepository scripts,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(function != null);
assert(functions != null);
assert(classes != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(scripts != null);
assert(objects != null);
FunctionViewElement e = new FunctionViewElement.created();
e._r = new RenderingScheduler<FunctionViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._function = function;
e._functions = functions;
e._classes = classes;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._scripts = scripts;
e._objects = objects;
if (function.dartOwner is M.LibraryRef) {
e._library = function.dartOwner;
}
return e;
}
FunctionViewElement.created() : super.created('function-view');
@override
attached() {
super.attached();
_r.enable();
_refresh();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
navBar(_createMenu()),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Function ${_function.name}',
new HRElement(),
new ObjectCommonElement(_isolate, _function, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createMembers(),
new HRElement(),
new DivElement()
..children = _function.location == null
? const []
: [
new SourceInsetElement(_isolate, _function.location,
_scripts, _objects, _events,
queue: _r.queue)
.element
],
]
];
}
List<Element> _createMenu() {
final menu = <Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
];
if (_library != null) {
menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
.element);
} else if (_function.dartOwner is M.ClassRef) {
menu.add(new NavClassMenuElement(_isolate, _function.dartOwner,
queue: _r.queue)
.element);
}
menu.addAll(<Element>[
navMenu(_function.name),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]);
return menu;
}
List<Element> _createMembers() {
final members = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'kind',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new SpanElement()
..text = '${_function.isStatic ? "static " : ""}'
'${_function.isConst ? "const " : ""}'
'${_functionKindToString(_function.kind)}'
]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'owner',
new DivElement()
..classes = ['memberName']
..children = <Element>[
_function.dartOwner == null
? (new SpanElement()..text = '...')
: anyRef(_isolate, _function.dartOwner, _objects,
queue: _r.queue)
]
]
];
if (_function.field != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'script',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new FieldRefElement(_isolate, _function.field, _objects,
queue: _r.queue)
.element
]
]);
}
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'script',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new SourceLinkElement(_isolate, _function.location, _scripts,
queue: _r.queue)
.element
]
]);
if (_function.code != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'current code',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new CodeRefElement(_isolate, _function.code, queue: _r.queue)
.element
]
]);
}
if (_function.unoptimizedCode != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'unoptimized code',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new CodeRefElement(_isolate, _function.unoptimizedCode,
queue: _r.queue)
.element,
new SpanElement()
..title = 'This count is used to determine when a function '
'will be optimized. It is a combination of call '
'counts and other factors.'
..text = ' (usage count: ${function.usageCounter})'
]
]);
}
members.add(new DivElement()
..classes = ['memberItem']
..text = ' ');
if (_function.icDataArray != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'ic data array',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new InstanceRefElement(_isolate, _function.icDataArray, _objects,
queue: _r.queue)
.element
]
]);
}
members.addAll([
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'deoptimizations',
new DivElement()
..classes = ['memberName']
..text = '${_function.deoptimizations}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'optimizable',
new DivElement()
..classes = ['memberName']
..text = _function.isOptimizable ? 'yes' : 'no'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'inlinable',
new DivElement()
..classes = ['memberName']
..text = _function.isInlinable ? 'yes' : 'no'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'intrinsic',
new DivElement()
..classes = ['memberName']
..text = _function.hasIntrinsic ? 'yes' : 'no'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'recognized',
new DivElement()
..classes = ['memberName']
..text = _function.isRecognized ? 'yes' : 'no'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'native',
new DivElement()
..classes = ['memberName']
..text = _function.isNative ? 'yes' : 'no'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'vm name',
new DivElement()
..classes = ['memberName']
..text = _function.vmName
]
]);
return members;
}
Future _refresh() async {
_function = await _functions.get(_isolate, _function.id);
if (_function.dartOwner is M.LibraryRef) {
_library = _function.dartOwner;
} else if (_function.dartOwner is M.ClassRef) {
_library = (await _classes.get(_isolate, _function.dartOwner.id)).library;
}
_r.dirty();
}
static String _functionKindToString(M.FunctionKind kind) {
switch (kind) {
case M.FunctionKind.regular:
return 'regular';
case M.FunctionKind.closure:
return 'closure';
case M.FunctionKind.implicitClosure:
return 'implicit closure';
case M.FunctionKind.getter:
return 'getter';
case M.FunctionKind.setter:
return 'setter';
case M.FunctionKind.constructor:
return 'constructor';
case M.FunctionKind.implicitGetter:
return 'implicit getter';
case M.FunctionKind.implicitSetter:
return 'implicit setter';
case M.FunctionKind.implicitStaticGetter:
return 'implicit static getter';
case M.FunctionKind.fieldInitializer:
return 'field initializer';
case M.FunctionKind.irregexpFunction:
return 'irregexp function';
case M.FunctionKind.methodExtractor:
return 'method extractor';
case M.FunctionKind.noSuchMethodDispatcher:
return 'noSuchMethod dispatcher';
case M.FunctionKind.invokeFieldDispatcher:
return 'invokeField dispatcher';
case M.FunctionKind.collected:
return 'collected';
case M.FunctionKind.native:
return 'native';
case M.FunctionKind.ffiTrampoline:
return 'ffi trampoline';
case M.FunctionKind.stub:
return 'stub';
case M.FunctionKind.tag:
return 'tag';
case M.FunctionKind.dynamicInvocationForwarder:
return 'dynamic invocation forwarder';
}
throw new Exception('Unknown Functionkind ($kind)');
}
}

View file

@ -1,71 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library general_error_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
class GeneralErrorElement extends CustomElement implements Renderable {
RenderingScheduler<GeneralErrorElement> _r;
Stream<RenderedEvent<GeneralErrorElement>> get onRendered => _r.onRendered;
M.NotificationRepository _notifications;
String _message;
String get message => _message;
set message(String value) => _message = _r.checkAndReact(_message, value);
factory GeneralErrorElement(M.NotificationRepository notifications,
{String message = '', RenderingQueue queue}) {
assert(notifications != null);
assert(message != null);
GeneralErrorElement e = new GeneralErrorElement.created();
e._r = new RenderingScheduler<GeneralErrorElement>(e, queue: queue);
e._message = message;
e._notifications = notifications;
return e;
}
GeneralErrorElement.created() : super.created('general-error');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered']
..children = <Element>[
new HeadingElement.h1()..text = 'Error',
new BRElement(),
new DivElement()
..classes = ['well']
..text = message
]
];
}
}

View file

@ -1,316 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library heap_map_element;
import 'dart:async';
import 'dart:html';
import 'dart:math';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/service.dart' as S;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
class HeapMapElement extends CustomElement implements Renderable {
RenderingScheduler<HeapMapElement> _r;
Stream<RenderedEvent<HeapMapElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
factory HeapMapElement(M.VM vm, M.IsolateRef isolate,
M.EventRepository events, M.NotificationRepository notifications,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
HeapMapElement e = new HeapMapElement.created();
e._r = new RenderingScheduler<HeapMapElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
return e;
}
HeapMapElement.created() : super.created('heap-map');
@override
attached() {
super.attached();
_r.enable();
_refresh();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
CanvasElement _canvas;
var _fragmentationData;
double _pageHeight;
final _classIdToColor = {};
final _colorToClassId = {};
final _classIdToName = {};
static final _freeColor = [255, 255, 255, 255];
static final _pageSeparationColor = [0, 0, 0, 255];
static const _PAGE_SEPARATION_HEIGHT = 4;
// Many browsers will not display a very tall canvas.
// TODO(koda): Improve interface for huge heaps.
static const _MAX_CANVAS_HEIGHT = 6000;
String _status;
S.ServiceMap _fragmentation;
void render() {
if (_canvas == null) {
_canvas = new CanvasElement()
..width = 1
..height = 1
..onMouseMove.listen(_handleMouseMove);
}
// Set hover text to describe the object under the cursor.
_canvas.title = _status;
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('heap map'),
(new NavRefreshElement(label: 'Mark-Compact', queue: _r.queue)
..onRefresh.listen((_) => _refresh(gc: "mark-compact")))
.element,
(new NavRefreshElement(label: 'Mark-Sweep', queue: _r.queue)
..onRefresh.listen((_) => _refresh(gc: "mark-sweep")))
.element,
(new NavRefreshElement(label: 'Scavenge', queue: _r.queue)
..onRefresh.listen((_) => _refresh(gc: "scavenge")))
.element,
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((_) => _refresh()))
.element,
(new NavNotifyElement(_notifications, queue: _r.queue)).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = _status,
new HRElement(),
],
new DivElement()
..classes = ['flex-row']
..children = <Element>[_canvas]
];
}
// Encode color as single integer, to enable using it as a map key.
int _packColor(Iterable<int> color) {
int packed = 0;
for (var component in color) {
packed = packed * 256 + component;
}
return packed;
}
void _addClass(int classId, String name, Iterable<int> color) {
_classIdToName[classId] = name.split('@')[0];
_classIdToColor[classId] = color;
_colorToClassId[_packColor(color)] = classId;
}
void _updateClassList(classList, int freeClassId) {
for (var member in classList['classes']) {
if (member is! S.Class) {
// TODO(turnidge): The printing for some of these non-class
// members is broken. Fix this:
//
// Logger.root.info('$member');
print('Ignoring non-class in class list');
continue;
}
var classId = int.parse(member.id.split('/').last);
var color = _classIdToRGBA(classId);
_addClass(classId, member.name, color);
}
_addClass(freeClassId, 'Free', _freeColor);
_addClass(0, '', _pageSeparationColor);
}
Iterable<int> _classIdToRGBA(int classId) {
// TODO(koda): Pick random hue, but fixed saturation and value.
var rng = new Random(classId);
return [rng.nextInt(128), rng.nextInt(128), rng.nextInt(128), 255];
}
String _classNameAt(Point<num> point) {
var color = new PixelReference(_fragmentationData, point).color;
return _classIdToName[_colorToClassId[_packColor(color)]];
}
ObjectInfo _objectAt(Point<num> point) {
if (_fragmentation == null || _canvas == null) {
return null;
}
var pagePixels = _pageHeight * _fragmentationData.width;
var index = new PixelReference(_fragmentationData, point).index;
var pageIndex = index ~/ pagePixels;
num pageOffset = index % pagePixels;
var pages = _fragmentation['pages'];
if (pageIndex < 0 || pageIndex >= pages.length) {
return null;
}
// Scan the page to find start and size.
var page = pages[pageIndex];
var objects = page['objects'];
var offset = 0;
var size = 0;
for (var i = 0; i < objects.length; i += 2) {
size = objects[i];
offset += size;
if (offset > pageOffset) {
pageOffset = offset - size;
break;
}
}
return new ObjectInfo(
int.parse(page['objectStart']) +
pageOffset * _fragmentation['unitSizeBytes'],
size * _fragmentation['unitSizeBytes']);
}
void _handleMouseMove(MouseEvent event) {
var info = _objectAt(event.offset);
if (info == null) {
_status = '';
_r.dirty();
return;
}
var addressString = '${info.size}B @ 0x${info.address.toRadixString(16)}';
var className = _classNameAt(event.offset);
_status = (className == '') ? '-' : '$className $addressString';
_r.dirty();
}
void _updateFragmentationData() {
if (_fragmentation == null || _canvas == null) {
return;
}
_updateClassList(
_fragmentation['classList'], _fragmentation['freeClassId']);
var pages = _fragmentation['pages'];
var width = max(_canvas.parent.client.width, 1);
_pageHeight = _PAGE_SEPARATION_HEIGHT +
_fragmentation['pageSizeBytes'] ~/
_fragmentation['unitSizeBytes'] ~/
width;
var height = min(_pageHeight * pages.length, _MAX_CANVAS_HEIGHT);
_fragmentationData = _canvas.context2D.createImageData(width, height);
_canvas.width = _fragmentationData.width;
_canvas.height = _fragmentationData.height;
_renderPages(0);
}
// Renders and draws asynchronously, one page at a time to avoid
// blocking the UI.
void _renderPages(int startPage) {
var pages = _fragmentation['pages'];
_status = 'Loaded $startPage of ${pages.length} pages';
_r.dirty();
var startY = (startPage * _pageHeight).round();
var endY = startY + _pageHeight.round();
if (startPage >= pages.length || endY > _fragmentationData.height) {
return;
}
var pixel = new PixelReference(_fragmentationData, new Point(0, startY));
var objects = pages[startPage]['objects'];
for (var i = 0; i < objects.length; i += 2) {
var count = objects[i];
var classId = objects[i + 1];
var color = _classIdToColor[classId];
while (count-- > 0) {
pixel.color = color;
pixel = pixel.next();
}
}
while (pixel.point.y < endY) {
pixel.color = _pageSeparationColor;
pixel = pixel.next();
}
_canvas.context2D.putImageData(
_fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY);
// Continue with the next page, asynchronously.
new Future(() {
_renderPages(startPage + 1);
});
}
Future _refresh({String gc}) {
final isolate = _isolate as S.Isolate;
var params = {};
if (gc != null) {
params['gc'] = gc;
}
return isolate.invokeRpc('_getHeapMap', params).then((serviceObject) {
S.ServiceMap response = serviceObject;
assert(response['type'] == 'HeapMap');
_fragmentation = response;
_updateFragmentationData();
});
}
}
// A reference to a particular pixel of ImageData.
class PixelReference {
final _data;
var _dataIndex;
static const NUM_COLOR_COMPONENTS = 4;
PixelReference(ImageData data, Point<num> point)
: _data = data,
_dataIndex = (point.y * data.width + point.x) * NUM_COLOR_COMPONENTS;
PixelReference._fromDataIndex(this._data, this._dataIndex);
Point<num> get point => new Point(index % _data.width, index ~/ _data.width);
void set color(Iterable<int> color) {
_data.data.setRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS, color);
}
Iterable<int> get color =>
_data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS);
// Returns the next pixel in row-major order.
PixelReference next() => new PixelReference._fromDataIndex(
_data, _dataIndex + NUM_COLOR_COMPONENTS);
// The row-major index of this pixel.
int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS;
}
class ObjectInfo {
final address;
final size;
ObjectInfo(this.address, this.size);
}

File diff suppressed because it is too large Load diff

View file

@ -1,100 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/code_ref.dart';
import 'package:observatory_2/src/elements/context_ref.dart';
import 'package:observatory_2/src/elements/error_ref.dart';
import 'package:observatory_2/src/elements/field_ref.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/icdata_ref.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
import 'package:observatory_2/src/elements/library_ref.dart';
import 'package:observatory_2/src/elements/local_var_descriptors_ref.dart';
import 'package:observatory_2/src/elements/megamorphiccache_ref.dart';
import 'package:observatory_2/src/elements/objectpool_ref.dart';
import 'package:observatory_2/src/elements/pc_descriptors_ref.dart';
import 'package:observatory_2/src/elements/script_ref.dart';
import 'package:observatory_2/src/elements/sentinel_value.dart';
import 'package:observatory_2/src/elements/singletargetcache_ref.dart';
import 'package:observatory_2/src/elements/subtypetestcache_ref.dart';
import 'package:observatory_2/src/elements/type_arguments_ref.dart';
import 'package:observatory_2/src/elements/unknown_ref.dart';
import 'package:observatory_2/src/elements/unlinkedcall_ref.dart';
Element anyRef(M.IsolateRef isolate, ref, M.ObjectRepository objects,
{RenderingQueue queue, bool expandable = true}) {
if (ref == null) {
return new SpanElement()..text = "???";
}
if (ref is M.Guarded) {
if (ref.isSentinel) {
return anyRef(isolate, ref.asSentinel, objects,
queue: queue, expandable: expandable);
} else {
return anyRef(isolate, ref.asValue, objects,
queue: queue, expandable: expandable);
}
} else if (ref is M.ObjectRef) {
if (ref is M.ClassRef) {
return new ClassRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.CodeRef) {
return new CodeRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.ContextRef) {
return new ContextRefElement(isolate, ref, objects,
queue: queue, expandable: expandable)
.element;
} else if (ref is M.Error) {
return new ErrorRefElement(ref, queue: queue).element;
} else if (ref is M.FieldRef) {
return new FieldRefElement(isolate, ref, objects,
queue: queue, expandable: expandable)
.element;
} else if (ref is M.FunctionRef) {
return new FunctionRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.ICDataRef) {
return new ICDataRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.InstanceRef) {
return new InstanceRefElement(isolate, ref, objects,
queue: queue, expandable: expandable)
.element;
} else if (ref is M.LibraryRef) {
return new LibraryRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.LocalVarDescriptorsRef) {
return new LocalVarDescriptorsRefElement(isolate, ref, queue: queue)
.element;
} else if (ref is M.MegamorphicCacheRef) {
return new MegamorphicCacheRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.ObjectPoolRef) {
return new ObjectPoolRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.PcDescriptorsRef) {
return new PcDescriptorsRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.ScriptRef) {
return new ScriptRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.SingleTargetCacheRef) {
return new SingleTargetCacheRefElement(isolate, ref, queue: queue)
.element;
} else if (ref is M.SubtypeTestCacheRef) {
return new SubtypeTestCacheRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.TypeArgumentsRef) {
return new TypeArgumentsRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.UnknownObjectRef) {
return new UnknownObjectRefElement(isolate, ref, queue: queue).element;
} else if (ref is M.UnlinkedCallRef) {
return new UnlinkedCallRefElement(isolate, ref, queue: queue).element;
} else {
return new AnchorElement(href: Uris.inspect(isolate, object: ref))
..text = 'object';
}
} else if (ref is M.Sentinel) {
return new SentinelValueElement(ref, queue: queue).element;
} else if (ref is num || ref is String) {
return new SpanElement()..text = ref.toString();
}
throw new Exception('Unknown ref type (${ref.runtimeType})');
}

View file

@ -1,87 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
HtmlElement element(CustomElement e) => e.element;
class CustomElement {
static Expando reverseElements = new Expando();
static CustomElement reverse(HtmlElement element) => reverseElements[element];
static List<CustomElement> toBeAttached = <CustomElement>[];
static void drainAttached() {
// Send 'attached' to elements that have been attached to the document.
bool fired = false;
var connectedElements = toBeAttached
.where((CustomElement element) => element.element.isConnected)
.toList();
for (CustomElement element in connectedElements) {
toBeAttached.remove(element);
element.attached();
fired = true;
}
if (toBeAttached.isEmpty) {
return; // Done.
}
if (fired) {
// The 'attached' events above may have scheduled microtasks that will
// will add more CustomElements to be document, e.g. 'render'.
scheduleMicrotask(() => drainAttached());
}
while (!toBeAttached.isEmpty) {
// Either this element will never be attached or it will be attached
// after a turn of the outer event loop. Fire 'attached' in case it is
// the latter, since firing it out of order is preferable to not firing
// it at all.
CustomElement element = toBeAttached.removeLast();
print("Warning: created but not in document: $element");
element.attached();
}
}
final HtmlElement element;
CustomElement.created(String elementClass)
: element = document.createElement("shadow") {
reverseElements[element] = this;
element.classes = [elementClass];
if (toBeAttached.isEmpty) {
scheduleMicrotask(() => drainAttached());
}
toBeAttached.add(this);
}
void attached() {}
void detached() {}
Element get parent => element.parent;
List<Element> get children => element.children;
set children(List<Element> c) => element.children = c;
CssClassSet get classes => element.classes;
set classes(dynamic c) => element.classes = c;
String get title => element.title;
set title(String t) => element.title = t;
String get text => element.text;
set text(String t) => element.text = t;
CssStyleDeclaration get style => element.style;
ElementStream<MouseEvent> get onClick => element.onClick;
Rectangle getBoundingClientRect() => element.getBoundingClientRect();
List<Node> getElementsByClassName(String c) =>
element.getElementsByClassName(c);
void scrollIntoView() => element.scrollIntoView();
}

View file

@ -1,14 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
Element navBar(Iterable<Element> content) {
assert(content != null);
return document.createElement('nav')
..classes = ['nav-bar']
..children = <Element>[
new UListElement()..children = content,
];
}

View file

@ -1,20 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
navMenu(String label, {String link, Iterable<Element> content = const []}) {
assert(label != null);
assert(content != null);
return new LIElement()
..classes = ['nav-menu']
..children = <Element>[
new SpanElement()
..classes = ['nav-menu_label']
..children = <Element>[
new AnchorElement(href: link)..text = label,
new UListElement()..children = content
]
];
}

View file

@ -1,87 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:collection';
import 'dart:async';
/// A generic rendering task that can be scheduled.
abstract class RenderingTask {
/// Rendering synchronous callback.
void render();
}
/// A generic synchronization system for rendering operations.
abstract class RenderingBarrier {
/// Future to the next synchronization barrier (ms from application start).
Future<num> get next;
}
/// Synchronization system based on the AnimationFrame.
class NextAnimationFrameBarrier implements RenderingBarrier {
Future<num> get next => window.animationFrame;
}
/// MOCK synchronization system for manual barrier triggering.
class RenderingBarrierMock implements RenderingBarrier {
final StreamController<num> _stream = new StreamController<num>.broadcast();
num _ms = 0;
Future<num> get next => _stream.stream.first;
/// Trigger the next barrier with an optional numer of ms elapsed.
void triggerRenderingBarrier({num step = 20}) {
assert(step != null);
_stream.add(_ms += step);
}
}
/// RenderingTask queuing and synchronization system.
class RenderingQueue {
final RenderingBarrier _barrier;
final Queue<RenderingTask> _queue = new Queue<RenderingTask>();
bool get isEmpty => _queue.isEmpty;
bool get isNotEmpty => _queue.isNotEmpty;
/// Creates a RenderingQueue with the default synchronization barrier.
RenderingQueue() : this.fromBarrier(new NextAnimationFrameBarrier());
/// Creates a RenderingQueue with a custom synchronization barrier.
RenderingQueue.fromBarrier(this._barrier) {
assert(this._barrier != null);
}
/// Add a task to the queue.
/// If the current rendering phase is running it will be executed during this
/// rendering cycle, otherwise it will be queued for the next one.
void enqueue(RenderingTask r, {bool waitForBarrier = true}) {
assert(r != null);
final wasEmpty = _queue.isEmpty;
_queue.addLast(r);
// If no task are in the queue there is no rendering phase scheduled.
if (wasEmpty) {
if (waitForBarrier) {
_render();
} else {
// We schedule the _renderLoop as a microtask to allow the
// scheduleRendering method to terminate, due to the fact that it is
// generally invoked from inside a HtmlElement.attached method
scheduleMicrotask(_renderLoop);
}
}
}
Future _render() async {
await _barrier.next;
_renderLoop();
}
void _renderLoop() {
while (_queue.isNotEmpty) {
_queue.first.render();
_queue.removeFirst();
}
}
}

View file

@ -1,141 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
export 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
/// A generic renderable object.
abstract class Renderable {
void render();
}
/// Event related to a Renderable rendering phase.
class RenderedEvent<T> {
/// Renderable to which the event is related
final T element;
/// Is another rendering scheduled for this element.
final bool otherRenderScheduled;
RenderedEvent(this.element, this.otherRenderScheduled) {
assert(element != null);
assert(otherRenderScheduled != null);
}
}
/// Scheduler for rendering operations.
class RenderingScheduler<T extends Renderable> implements RenderingTask {
bool _enabled = false;
bool _dirty = false;
bool _renderingScheduled = false;
bool _notificationScheduled = false;
bool _waitForBarrier = false;
/// Element managed by this scheduler.
final T element;
/// Queue used for rendering operations.
final RenderingQueue queue;
final List<Future> _wait = <Future>[];
/// Does the element need a new rendering cycle.
bool get isDirty => _dirty;
/// Is the scheduler enabled.
bool get isEnabled => _enabled;
final StreamController<RenderedEvent<T>> _onRendered =
new StreamController<RenderedEvent<T>>.broadcast();
Stream<RenderedEvent<T>> get onRendered => _onRendered.stream;
/// Creates a new scheduler for an element.
/// If no queue is provided it will create a new default configured queue.
factory RenderingScheduler(T element, {RenderingQueue queue}) {
assert(element != null);
if (queue == null) {
queue = new RenderingQueue();
}
return new RenderingScheduler<T>._(element, queue);
}
RenderingScheduler._(this.element, this.queue);
/// Enable the scheduler.
/// New dirty or schedule request will be considered.
void enable() {
if (_enabled) return;
_enabled = true;
scheduleRendering();
}
/// Disable the scheduler.
/// New dirty or schedule request will be discarded.
/// [optional] notify: send a final RenderEvent.
void disable({bool notify = false}) {
assert(notify != null);
if (!_enabled) return;
_enabled = false;
if (notify) scheduleNotification();
}
/// Set the object as dirty. A rendering will be scheduled.
void dirty() {
if (_dirty) return;
_dirty = true;
scheduleRendering();
}
/// Checks for modification during attribute set.
/// If value changes a new rendering is scheduled.
/// set attr(T v) => _attr = _r.checkAndReact(_attr, v);
T checkAndReact<T>(T oldValue, T newValue) {
if (oldValue != newValue)
dirty();
else
scheduleNotification();
return newValue;
}
/// Schedules a new rendering phase.
void scheduleRendering() {
if (_renderingScheduled) return;
if (!_enabled) return;
queue.enqueue(this, waitForBarrier: _waitForBarrier);
_waitForBarrier = true;
_renderingScheduled = true;
}
/// Renders the element (if the scheduler is enabled).
/// It will clear the dirty flag.
void render() {
_renderingScheduled = false;
if (!_enabled) return;
_dirty = false;
_wait.clear();
element.render();
scheduleNotification();
if (_dirty) scheduleRendering();
}
/// Schedules a notification.
void scheduleNotification() {
if (_notificationScheduled) return;
_notify();
_notificationScheduled = true;
}
void waitFor(Iterable<Future> it) {
_wait.addAll(it);
}
Future _notify() async {
await Future.wait(_wait);
_wait.clear();
_onRendered.add(new RenderedEvent<T>(element, _dirty));
_notificationScheduled = false;
}
}

View file

@ -1,97 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
HtmlElement element(CustomElement e) => e.element;
class CustomElement {
static Expando reverseElements = new Expando();
static CustomElement reverse(HtmlElement element) => reverseElements[element];
static List<CustomElement> toBeAttached = <CustomElement>[];
static void drainAttached() {
// Send 'attached' to elements that have been attached to the document.
bool fired = false;
var connectedElements = toBeAttached
.where((CustomElement element) => element.element.isConnected)
.toList();
for (CustomElement element in connectedElements) {
toBeAttached.remove(element);
element.attached();
fired = true;
}
if (toBeAttached.isEmpty) {
return; // Done.
}
if (fired) {
// The 'attached' events above may have scheduled microtasks that will
// will add more CustomElements to be document, e.g. 'render'.
scheduleMicrotask(() => drainAttached());
}
while (!toBeAttached.isEmpty) {
// Either this element will never be attached or it will be attached
// after a turn of the outer event loop. Fire 'attached' in case it is
// the latter, since firing it out of order is preferable to not firing
// it at all.
CustomElement element = toBeAttached.removeLast();
print("Warning: created but not in document: $element");
element.attached();
}
}
final HtmlElement element;
CustomElement.created(Tag tag) : element = document.createElement("shadow") {
reverseElements[element] = this;
element.classes = [tag.name];
if (toBeAttached.isEmpty) {
scheduleMicrotask(() => drainAttached());
}
toBeAttached.add(this);
}
void attached() {}
void detached() {}
Element get parent => element.parent;
List<Element> get children => element.children;
set children(List<Element> c) => element.children = c;
CssClassSet get classes => element.classes;
set classes(dynamic c) => element.classes = c;
String get title => element.title;
set title(String t) => element.title = t;
String get text => element.text;
set text(String t) => element.text = t;
CssStyleDeclaration get style => element.style;
ElementStream<MouseEvent> get onClick => element.onClick;
Rectangle getBoundingClientRect() => element.getBoundingClientRect();
List<Node> getElementsByClassName(String c) =>
element.getElementsByClassName(c);
void scrollIntoView() => element.scrollIntoView();
}
/// Utility class for Custom Tags registration.
class Tag<T extends CustomElement> {
/// Tag name.
final String name;
/// Dependent tags that need to be registered for this tag to work properly.
final Iterable<Tag> dependencies;
const Tag(this.name, {this.dependencies = const []});
}

View file

@ -1,52 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:observatory_2/models.dart' as M;
/// Utility class for URIs generation.
abstract class Uris {
static String _isolatePage(String path, M.IsolateRef isolate,
{M.ObjectRef object}) {
final parameters = {'isolateId': isolate.id};
if (object != null) parameters['objectId'] = object.id;
return '#' + new Uri(path: path, queryParameters: parameters).toString();
}
static String allocationProfiler(M.IsolateRef isolate) =>
_isolatePage('/allocation-profiler', isolate);
static String classTree(M.IsolateRef isolate) =>
_isolatePage('/class-tree', isolate);
static String cpuProfiler(M.IsolateRef isolate) =>
_isolatePage('/profiler', isolate);
static String cpuProfilerTable(M.IsolateRef isolate) =>
_isolatePage('/profiler-table', isolate);
static String debugger(M.IsolateRef isolate) =>
_isolatePage('/debugger', isolate);
static String flags() => '#/flags';
static String heapMap(M.IsolateRef isolate) =>
_isolatePage('/heap-map', isolate);
static String heapSnapshot(M.IsolateRef isolate) =>
_isolatePage('/heap-snapshot', isolate);
static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
if (pos == null) {
return _isolatePage('/inspect', isolate, object: object);
}
return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
}
static String logging(M.IsolateRef isolate) =>
_isolatePage('/logging', isolate);
static String metrics(M.IsolateRef isolate) =>
_isolatePage('/metrics', isolate);
static String nativeMemory() => '#/native-memory-profile';
static String processSnapshot() => '#/process-snapshot';
static String objectStore(M.IsolateRef isolate) =>
_isolatePage('/object-store', isolate);
static String persistentHandles(M.IsolateRef isolate) =>
_isolatePage('/persistent-handles', isolate);
static String ports(M.IsolateRef isolate) => _isolatePage('/ports', isolate);
static String timeline() => '#/timeline';
static String vm() => '#/vm';
static String vmConnect() => '#/vm-connect';
}

View file

@ -1,60 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M show IsolateRef, ICDataRef;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class ICDataRefElement extends CustomElement implements Renderable {
RenderingScheduler<ICDataRefElement> _r;
Stream<RenderedEvent<ICDataRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.ICDataRef _icdata;
M.IsolateRef get isolate => _isolate;
M.ICDataRef get icdata => _icdata;
factory ICDataRefElement(M.IsolateRef isolate, M.ICDataRef icdata,
{RenderingQueue queue}) {
assert(isolate != null);
assert(icdata != null);
ICDataRefElement e = new ICDataRefElement.created();
e._r = new RenderingScheduler<ICDataRefElement>(e, queue: queue);
e._isolate = isolate;
e._icdata = icdata;
return e;
}
ICDataRefElement.created() : super.created('icdata-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
new AnchorElement(href: Uris.inspect(_isolate, object: _icdata))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = 'ICData',
new SpanElement()..text = ' (${_icdata.selector})'
]
];
}
}

View file

@ -1,185 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
class ICDataViewElement extends CustomElement implements Renderable {
RenderingScheduler<ICDataViewElement> _r;
Stream<RenderedEvent<ICDataViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.ICData _icdata;
M.ICDataRepository _icdatas;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ObjectRepository _objects;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.ICData get icdata => _icdata;
factory ICDataViewElement(
M.VM vm,
M.IsolateRef isolate,
M.ICData icdata,
M.EventRepository events,
M.NotificationRepository notifications,
M.ICDataRepository icdatas,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(icdata != null);
assert(icdatas != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(objects != null);
ICDataViewElement e = new ICDataViewElement.created();
e._r = new RenderingScheduler<ICDataViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._icdata = icdata;
e._icdatas = icdatas;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._objects = objects;
return e;
}
ICDataViewElement.created() : super.created('icdata-view');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('icdata'),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_icdata = await _icdatas.get(_isolate, _icdata.id);
_r.dirty();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'ICData',
new HRElement(),
new ObjectCommonElement(_isolate, _icdata, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'selector',
new DivElement()
..classes = ['memberName']
..text = _icdata.selector
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'owner',
new DivElement()
..classes = ['memberName']
..children = <Element>[
_icdata.dartOwner == null
? (new SpanElement()..text = '<none>')
: anyRef(_isolate, _icdata.dartOwner, _objects,
queue: _r.queue)
]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'argumentsDescriptor',
new DivElement()
..classes = ['memberName']
..children = <Element>[
_icdata.argumentsDescriptor == null
? (new SpanElement()..text = '<none>')
: anyRef(
_isolate, _icdata.argumentsDescriptor, _objects,
queue: _r.queue)
]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'entries',
new DivElement()
..classes = ['memberName']
..children = <Element>[
_icdata.entries == null
? (new SpanElement()..text = '<none>')
: anyRef(_isolate, _icdata.entries, _objects,
queue: _r.queue)
]
]
],
]
];
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

View file

@ -1,117 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class InboundReferencesElement extends CustomElement implements Renderable {
RenderingScheduler<InboundReferencesElement> _r;
Stream<RenderedEvent<InboundReferencesElement>> get onRendered =>
_r.onRendered;
M.IsolateRef _isolate;
M.ObjectRef _object;
M.InboundReferencesRepository _references;
M.ObjectRepository _objects;
M.InboundReferences _inbounds;
bool _expanded = false;
M.IsolateRef get isolate => _isolate;
M.ObjectRef get object => _object;
factory InboundReferencesElement(M.IsolateRef isolate, M.ObjectRef object,
M.InboundReferencesRepository references, M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(isolate != null);
assert(object != null);
assert(references != null);
assert(objects != null);
InboundReferencesElement e = new InboundReferencesElement.created();
e._r = new RenderingScheduler<InboundReferencesElement>(e, queue: queue);
e._isolate = isolate;
e._object = object;
e._references = references;
e._objects = objects;
return e;
}
InboundReferencesElement.created() : super.created('inbound-references');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
final curlyBlock =
new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
..content = _createContent()
..onToggle.listen((e) async {
_expanded = e.control.expanded;
if (_expanded) {
e.control.disabled = true;
await _refresh();
e.control.disabled = false;
}
});
children = <Element>[curlyBlock.element];
_r.waitFor([curlyBlock.onRendered.first]);
}
Future _refresh() async {
_inbounds = await _references.get(_isolate, _object.id);
_r.dirty();
}
List<Element> _createContent() {
if (_inbounds == null) {
return const [];
}
return _inbounds.elements.map<Element>(_createItem).toList();
}
Element _createItem(M.InboundReference reference) {
final content = <Element>[];
if (reference.parentField != null) {
content.addAll([
new SpanElement()..text = 'referenced by ',
anyRef(_isolate, reference.parentField, _objects, queue: _r.queue),
new SpanElement()..text = ' of '
]);
} else if (reference.parentListIndex != null) {
content.add(new SpanElement()
..text = 'referenced by [ ${reference.parentListIndex} ] of ');
} else if (reference.parentWordOffset != null) {
content.add(new SpanElement()
..text = 'referenced by offset ${reference.parentWordOffset} of ');
}
content.addAll([
anyRef(_isolate, reference.source, _objects, queue: _r.queue),
new InboundReferencesElement(
_isolate, reference.source, _references, _objects,
queue: _r.queue)
.element
]);
return new DivElement()
..classes = ['indent']
..children = content;
}
}

View file

@ -1,366 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/field_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/utils.dart';
class InstanceRefElement extends CustomElement implements Renderable {
RenderingScheduler<InstanceRefElement> _r;
Stream<RenderedEvent<InstanceRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.InstanceRef _instance;
M.ObjectRepository _objects;
M.Instance _loadedInstance;
bool _expandable;
bool _expanded = false;
M.IsolateRef get isolate => _isolate;
M.InstanceRef get instance => _instance;
factory InstanceRefElement(
M.IsolateRef isolate, M.InstanceRef instance, M.ObjectRepository objects,
{RenderingQueue queue, bool expandable = true}) {
assert(isolate != null);
assert(instance != null);
assert(objects != null);
InstanceRefElement e = new InstanceRefElement.created();
e._r = new RenderingScheduler<InstanceRefElement>(e, queue: queue);
e._isolate = isolate;
e._instance = instance;
e._objects = objects;
e._expandable = expandable;
return e;
}
InstanceRefElement.created() : super.created('instance-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
final content = _createLink();
if (_expandable && _hasValue()) {
content.addAll([
new SpanElement()..text = ' ',
(new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['indent']
..children = _createValue()
]
..onToggle.listen((e) async {
_expanded = e.control.expanded;
if (_expanded) {
e.control.disabled = true;
await _refresh();
e.control.disabled = false;
}
}))
.element
]);
}
children = content;
}
Future _refresh() async {
_loadedInstance = await _objects.get(_isolate, _instance.id);
_r.dirty();
}
List<Element> _createShowMoreButton() {
if (_loadedInstance.count == null) {
return [];
}
final count = _loadedInstance.count;
final button = new ButtonElement()..text = 'show next ${count}';
button.onClick.listen((_) async {
button.disabled = true;
_loadedInstance = await _objects.get(_isolate, _instance.id);
_r.dirty();
});
return [button];
}
List<Element> _createLink() {
switch (_instance.kind) {
case M.InstanceKind.vNull:
case M.InstanceKind.bool:
case M.InstanceKind.int:
case M.InstanceKind.double:
case M.InstanceKind.float32x4:
case M.InstanceKind.float64x2:
case M.InstanceKind.int32x4:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..text = _instance.valueAsString
];
case M.InstanceKind.string:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..text = Utils.formatStringAsLiteral(
_instance.valueAsString, _instance.valueAsStringIsTruncated)
];
case M.InstanceKind.type:
case M.InstanceKind.functionType:
case M.InstanceKind.typeParameter:
case M.InstanceKind.recordType:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..text = _instance.name
];
case M.InstanceKind.closure:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = 'Closure',
new SpanElement()..text = ' (${_instance.closureFunction.name})'
]
];
case M.InstanceKind.regExp:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = _instance.clazz.name,
new SpanElement()..text = ' (${_instance.pattern.valueAsString})'
]
];
case M.InstanceKind.stackTrace:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = _instance.clazz.name,
]
];
case M.InstanceKind.plainInstance:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..classes = ['emphasize']
..text = _instance.clazz.name
];
case M.InstanceKind.list:
case M.InstanceKind.map:
case M.InstanceKind.set:
case M.InstanceKind.uint8ClampedList:
case M.InstanceKind.uint8List:
case M.InstanceKind.uint16List:
case M.InstanceKind.uint32List:
case M.InstanceKind.uint64List:
case M.InstanceKind.int8List:
case M.InstanceKind.int16List:
case M.InstanceKind.int32List:
case M.InstanceKind.int64List:
case M.InstanceKind.float32List:
case M.InstanceKind.float64List:
case M.InstanceKind.int32x4List:
case M.InstanceKind.float32x4List:
case M.InstanceKind.float64x2List:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = _instance.clazz.name,
new SpanElement()..text = ' (${_instance.length})'
]
];
case M.InstanceKind.mirrorReference:
case M.InstanceKind.weakProperty:
case M.InstanceKind.finalizer:
case M.InstanceKind.weakReference:
case M.InstanceKind.record:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..classes = ['emphasize']
..text = _instance.clazz.name
];
}
throw new Exception('Unknown InstanceKind: ${_instance.kind}');
}
bool _hasValue() {
switch (_instance.kind) {
case M.InstanceKind.closure:
case M.InstanceKind.plainInstance:
case M.InstanceKind.mirrorReference:
case M.InstanceKind.stackTrace:
case M.InstanceKind.weakReference:
case M.InstanceKind.weakProperty:
case M.InstanceKind.recordType:
return true;
case M.InstanceKind.list:
case M.InstanceKind.map:
case M.InstanceKind.set:
case M.InstanceKind.uint8ClampedList:
case M.InstanceKind.uint8List:
case M.InstanceKind.uint16List:
case M.InstanceKind.uint32List:
case M.InstanceKind.uint64List:
case M.InstanceKind.int8List:
case M.InstanceKind.int16List:
case M.InstanceKind.int32List:
case M.InstanceKind.int64List:
case M.InstanceKind.float32List:
case M.InstanceKind.float64List:
case M.InstanceKind.int32x4List:
case M.InstanceKind.float32x4List:
case M.InstanceKind.float64x2List:
return _instance.length > 0;
default:
return false;
}
}
List<Element> _createValue() {
if (_loadedInstance == null) {
return [new SpanElement()..text = 'Loading...'];
}
switch (_instance.kind) {
case M.InstanceKind.closure:
{
var members = <Element>[];
if (_loadedInstance.closureFunction != null) {
members.add(new DivElement()
..children = <Element>[
new SpanElement()..text = 'function = ',
anyRef(_isolate, _loadedInstance.closureFunction, _objects,
queue: _r.queue)
]);
}
if (_loadedInstance.closureContext != null) {
members.add(new DivElement()
..children = <Element>[
new SpanElement()..text = 'context = ',
anyRef(_isolate, _loadedInstance.closureContext, _objects,
queue: _r.queue)
]);
}
return members;
}
case M.InstanceKind.plainInstance:
case M.InstanceKind.receivePort:
return _loadedInstance.fields
.map<Element>((f) => new DivElement()
..children = <Element>[
new FieldRefElement(_isolate, f.decl, _objects, queue: _r.queue)
.element,
new SpanElement()..text = ' = ',
anyRef(_isolate, f.value, _objects, queue: _r.queue)
])
.toList();
case M.InstanceKind.list:
var index = 0;
return _loadedInstance.elements
.map<Element>((element) => new DivElement()
..children = <Element>[
new SpanElement()..text = '[ ${index++} ] : ',
anyRef(_isolate, element, _objects, queue: _r.queue)
])
.toList()
..addAll(_createShowMoreButton());
case M.InstanceKind.map:
return _loadedInstance.associations
.map<Element>((association) => new DivElement()
..children = <Element>[
new SpanElement()..text = '[ ',
anyRef(_isolate, association.key, _objects, queue: _r.queue),
new SpanElement()..text = ' ] : ',
anyRef(_isolate, association.value, _objects, queue: _r.queue)
])
.toList()
..addAll(_createShowMoreButton());
case M.InstanceKind.set:
return _loadedInstance.elements
.map<Element>((element) => new DivElement()
..children = <Element>[
anyRef(_isolate, element, _objects, queue: _r.queue)
])
.toList()
..addAll(_createShowMoreButton());
case M.InstanceKind.uint8ClampedList:
case M.InstanceKind.uint8List:
case M.InstanceKind.uint16List:
case M.InstanceKind.uint32List:
case M.InstanceKind.uint64List:
case M.InstanceKind.int8List:
case M.InstanceKind.int16List:
case M.InstanceKind.int32List:
case M.InstanceKind.int64List:
case M.InstanceKind.float32List:
case M.InstanceKind.float64List:
case M.InstanceKind.int32x4List:
case M.InstanceKind.float32x4List:
case M.InstanceKind.float64x2List:
var index = 0;
return _loadedInstance.typedElements
.map<Element>((e) => new DivElement()..text = '[ ${index++} ] : $e')
.toList()
..addAll(_createShowMoreButton());
case M.InstanceKind.mirrorReference:
return [
new SpanElement()..text = '<referent> : ',
anyRef(_isolate, _loadedInstance.referent, _objects, queue: _r.queue)
];
case M.InstanceKind.stackTrace:
return [
new DivElement()
..classes = ['stackTraceBox']
..text = _instance.valueAsString
];
case M.InstanceKind.weakReference:
return [
new SpanElement()..text = '<target> : ',
anyRef(_isolate, _loadedInstance.target, _objects, queue: _r.queue)
];
case M.InstanceKind.weakProperty:
return [
new SpanElement()..text = '<key> : ',
anyRef(_isolate, _loadedInstance.key, _objects, queue: _r.queue),
new BRElement(),
new SpanElement()..text = '<value> : ',
anyRef(_isolate, _loadedInstance.value, _objects, queue: _r.queue),
];
case M.InstanceKind.recordType:
final fields = _loadedInstance.fields.toList();
return [
for (int i = 0; i < fields.length; ++i) ...[
new SpanElement()..text = '${fields[i].name} = ',
new InstanceRefElement(_isolate, fields[i].value.asValue, _objects,
queue: _r.queue)
.element,
if (i + 1 != fields.length) new BRElement(),
]
];
default:
return [];
}
}
}

View file

@ -1,523 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library instance_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/eval_box.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
import 'package:observatory_2/src/elements/nav/class_menu.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/library_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/source_inset.dart';
import 'package:observatory_2/utils.dart';
class InstanceViewElement extends CustomElement implements Renderable {
RenderingScheduler<InstanceViewElement> _r;
Stream<RenderedEvent<InstanceViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Instance _instance;
M.LibraryRef _library;
M.ObjectRepository _objects;
M.ClassRepository _classes;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ScriptRepository _scripts;
M.EvalRepository _eval;
M.TypeArguments _typeArguments;
M.TypeArgumentsRepository _arguments;
M.BreakpointRepository _breakpoints;
M.FunctionRepository _functions;
M.SourceLocation _location;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Instance get instance => _instance;
factory InstanceViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Instance instance,
M.EventRepository events,
M.NotificationRepository notifications,
M.ObjectRepository objects,
M.ClassRepository classes,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ScriptRepository scripts,
M.EvalRepository eval,
M.TypeArgumentsRepository arguments,
M.BreakpointRepository breakpoints,
M.FunctionRepository functions,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(instance != null);
assert(objects != null);
assert(classes != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(scripts != null);
assert(eval != null);
assert(arguments != null);
assert(breakpoints != null);
assert(functions != null);
InstanceViewElement e = new InstanceViewElement.created();
e._r = new RenderingScheduler<InstanceViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._instance = instance;
e._objects = objects;
e._classes = classes;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._scripts = scripts;
e._eval = eval;
e._arguments = arguments;
e._breakpoints = breakpoints;
e._functions = functions;
return e;
}
InstanceViewElement.created() : super.created('instance-view');
@override
attached() {
super.attached();
_r.enable();
_loadExtraData();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
final content = <Element>[
new HeadingElement.h2()
..text = M.isAbstractType(_instance.kind)
? 'type ${_instance.name}'
: 'instance of ${_instance.clazz.name}',
new HRElement(),
new ObjectCommonElement(_isolate, _instance, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = _createMembers(),
new HRElement(),
new EvalBoxElement(_isolate, _instance, _objects, _eval,
quickExpressions: const ['toString()', 'runtimeType'],
queue: _r.queue)
.element
];
if (_location != null) {
content.addAll([
new HRElement(),
new SourceInsetElement(_isolate, _location, _scripts, _objects, _events,
queue: _r.queue)
.element
]);
}
children = <Element>[
navBar(_createMenu()),
new DivElement()
..classes = ['content-centered-big']
..children = content
];
}
List<Element> _createMenu() {
final menu = <Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
];
if (_library != null) {
menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
.element);
}
menu.addAll(<Element>[
new NavClassMenuElement(_isolate, _instance.clazz, queue: _r.queue)
.element,
navMenu('instance'),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]);
return menu;
}
Element memberHalf(String cssClass, dynamic half) {
var result = new DivElement()..classes = [cssClass];
if (half is String) {
result.text = half;
} else {
result.children = <Element>[
anyRef(_isolate, half, _objects, queue: _r.queue)
];
}
return result;
}
Element member(dynamic name, dynamic value) {
return new DivElement()
..classes = ['memberItem']
..children = <Element>[
memberHalf('memberName', name),
memberHalf('memberValue', value),
];
}
List<Element> _createMembers() {
final members = <Element>[];
if (_instance.valueAsString != null) {
if (_instance.kind == M.InstanceKind.string) {
members.add(member(
'value as literal',
Utils.formatStringAsLiteral(
_instance.valueAsString, _instance.valueAsStringIsTruncated)));
} else {
members.add(member('value', _instance.valueAsString));
}
}
if (_instance.typeClass != null) {
members.add(member('type class', _instance.typeClass));
}
if (_typeArguments != null && _typeArguments.types.isNotEmpty) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'type arguments',
new DivElement()
..classes = ['memberValue']
..children = ([new SpanElement()..text = '< ']
..addAll(_typeArguments.types.expand((type) => [
new InstanceRefElement(_isolate, type, _objects,
queue: _r.queue)
.element,
new SpanElement()..text = ', '
]))
..removeLast()
..add(new SpanElement()..text = ' >'))
]);
}
if (_instance.parameterizedClass != null) {
members.add(member('parameterized class', _instance.parameterizedClass));
}
if (_instance.parameterIndex != null) {
members.add(member('parameter index', '${_instance.parameterIndex}'));
}
if (_instance.bound != null) {
members.add(member('bound', _instance.bound));
}
if (_instance.closureFunction != null) {
members.add(member('closure function', _instance.closureFunction));
}
if (_instance.closureContext != null) {
members.add(member('closure context', _instance.closureContext));
}
if (_instance.kind == M.InstanceKind.closure) {
ButtonElement btn;
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'closure breakpoint',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
btn = new ButtonElement()
..text = _instance.activationBreakpoint == null
? 'break on activation'
: 'remove'
..onClick.listen((_) {
btn.disabled = true;
_toggleBreakpoint();
})
]
]);
}
if (_instance.nativeFields != null && _instance.nativeFields.isNotEmpty) {
int i = 0;
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'native fields (${_instance.nativeFields.length})',
new DivElement()
..classes = ['memberName']
..children = <Element>[
(new CurlyBlockElement(
expanded: _instance.nativeFields.length <= 100,
queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = _instance.nativeFields
.map<Element>(
(f) => member('[ ${i++} ]', '[ ${f.value} ]'))
.toList()
])
.element
]
]);
}
if (_instance.fields != null && _instance.fields.isNotEmpty) {
final fields = _instance.fields.toList();
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'fields (${fields.length})',
new DivElement()
..classes = ['memberName']
..children = <Element>[
(new CurlyBlockElement(
expanded: fields.length <= 100, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = fields.map<Element>((f) {
final name = _instance.kind == M.InstanceKind.record
? f.name
: f.decl;
return member(name, f.value);
}).toList()
])
.element
]
]);
}
if (_instance.elements != null && _instance.elements.isNotEmpty) {
final elements = _instance.elements.toList();
int i = 0;
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'elements (${_instance.length})',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(
expanded: elements.length <= 100, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = elements
.map<Element>(
(element) => member('[ ${i++} ]', element))
.toList()
])
.element
]
]);
if (_instance.length != elements.length) {
members.add(member(
'...', '${_instance.length - elements.length} omitted elements'));
}
}
if (_instance.associations != null && _instance.associations.isNotEmpty) {
final associations = _instance.associations.toList();
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'associations (${_instance.length})',
new DivElement()
..classes = ['memberName']
..children = <Element>[
(new CurlyBlockElement(
expanded: associations.length <= 100, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = associations
.map<Element>((a) => new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..children = <Element>[
new SpanElement()..text = '[ ',
anyRef(_isolate, a.key, _objects,
queue: _r.queue),
new SpanElement()..text = ' ]',
],
new DivElement()
..classes = ['memberValue']
..children = <Element>[
anyRef(_isolate, a.value, _objects,
queue: _r.queue)
]
])
.toList()
])
.element
]
]);
if (_instance.length != associations.length) {
members.add(member('...',
'${_instance.length - associations.length} omitted elements'));
}
}
if (_instance.typedElements != null && _instance.typedElements.isNotEmpty) {
final typedElements = _instance.typedElements.toList();
int i = 0;
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'elements (${_instance.length})',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(
expanded: typedElements.length <= 100, queue: _r.queue)
..content = <Element>[
new DivElement()
..classes = ['memberList']
..children = typedElements
.map<Element>((e) => member('[ ${i++} ]', '$e'))
.toList()
])
.element
]
]);
if (_instance.length != typedElements.length) {
members.add(member('...',
'${_instance.length - typedElements.length} omitted elements'));
}
}
if (_instance.kind == M.InstanceKind.regExp) {
members.add(member('pattern', _instance.pattern));
members.add(
member('isCaseSensitive', _instance.isCaseSensitive ? 'yes' : 'no'));
members.add(member('isMultiLine', _instance.isMultiLine ? 'yes' : 'no'));
if (_instance.oneByteFunction != null) {
members.add(member('oneByteFunction', _instance.oneByteFunction));
}
if (_instance.twoByteFunction != null) {
members.add(member('twoByteFunction', _instance.twoByteFunction));
}
if (_instance.externalOneByteFunction != null) {
members.add(member(
'externalOneByteFunction', _instance.externalOneByteFunction));
}
if (_instance.externalTwoByteFunction != null) {
members.add(member(
'externalTwoByteFunction', _instance.externalTwoByteFunction));
}
if (_instance.oneByteBytecode != null) {
members.add(member('oneByteBytecode', _instance.oneByteBytecode));
}
if (_instance.twoByteBytecode != null) {
members.add(member('twoByteBytecode', _instance.twoByteBytecode));
}
}
if (_instance.kind == M.InstanceKind.mirrorReference) {
members.add(member('referent', _instance.referent));
}
if (_instance.kind == M.InstanceKind.weakReference) {
members.add(member('target', _instance.target));
}
if (_instance.kind == M.InstanceKind.weakProperty) {
members.add(member('key', _instance.key));
members.add(member('value', _instance.value));
}
return members;
}
Future _refresh() async {
_instance = await _objects.get(_isolate, _instance.id);
await _loadExtraData();
_r.dirty();
}
Future _loadExtraData() async {
_library = (await _classes.get(_isolate, _instance.clazz.id)).library;
if (_instance.typeArguments != null) {
_typeArguments =
await _arguments.get(_isolate, _instance.typeArguments.id);
} else {
_typeArguments = null;
}
if (_instance.closureFunction != null) {
_location = (await _functions.get(_isolate, _instance.closureFunction.id))
.location;
} else if (_instance.typeClass != null) {
_location =
(await _classes.get(_isolate, _instance.typeClass.id)).location;
}
_r.dirty();
}
Future _toggleBreakpoint() async {
if (_instance.activationBreakpoint == null) {
await _breakpoints.addOnActivation(_isolate, _instance);
} else {
await _breakpoints.remove(_isolate, _instance.activationBreakpoint);
}
await _refresh();
}
}

View file

@ -1,65 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class IsolateCounterChartElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateCounterChartElement> _r;
Stream<RenderedEvent<IsolateCounterChartElement>> get onRendered =>
_r.onRendered;
Map _counters;
StreamSubscription _subscription;
factory IsolateCounterChartElement(Map counters, {RenderingQueue queue}) {
assert(counters != null);
IsolateCounterChartElement e = new IsolateCounterChartElement.created();
e._r = new RenderingScheduler<IsolateCounterChartElement>(e, queue: queue);
e._counters = counters;
return e;
}
IsolateCounterChartElement.created() : super.created('isolate-counter-chart');
@override
void attached() {
super.attached();
_r.enable();
_subscription = window.onResize.listen((_) => _r.dirty());
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_subscription.cancel();
}
void render() {
var members = <Element>[];
_counters.forEach((key, value) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = key,
new DivElement()
..classes = ['memberValue']
..text = value,
]);
});
children = <Element>[
new DivElement()
..classes = ['memberList']
..children = members
];
}
}

View file

@ -1,119 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/source_link.dart';
class IsolateLocationElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateLocationElement> _r;
Stream<RenderedEvent<IsolateLocationElement>> get onRendered => _r.onRendered;
M.Isolate _isolate;
M.EventRepository _events;
M.ScriptRepository _scripts;
StreamSubscription _debugSubscription;
StreamSubscription _isolateSubscription;
factory IsolateLocationElement(
M.Isolate isolate, M.EventRepository events, M.ScriptRepository scripts,
{RenderingQueue queue}) {
assert(isolate != null);
assert(events != null);
assert(scripts != null);
IsolateLocationElement e = new IsolateLocationElement.created();
e._r = new RenderingScheduler<IsolateLocationElement>(e, queue: queue);
e._isolate = isolate;
e._events = events;
e._scripts = scripts;
return e;
}
IsolateLocationElement.created() : super.created('isolate-location');
@override
void attached() {
super.attached();
_r.enable();
_debugSubscription = _events.onDebugEvent.listen(_eventListener);
_isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_debugSubscription.cancel();
_isolateSubscription.cancel();
}
void render() {
switch (_isolate.status) {
case M.IsolateStatus.loading:
children = <Element>[new SpanElement()..text = 'not yet runnable'];
break;
case M.IsolateStatus.running:
children = <Element>[
new SpanElement()..text = 'at ',
new FunctionRefElement(
_isolate, M.topFrame(_isolate.pauseEvent).function,
queue: _r.queue)
.element,
new SpanElement()..text = ' (',
new SourceLinkElement(
_isolate, M.topFrame(_isolate.pauseEvent).location, _scripts,
queue: _r.queue)
.element,
new SpanElement()..text = ') '
];
break;
case M.IsolateStatus.paused:
if (_isolate.pauseEvent is M.PauseStartEvent) {
children = <Element>[new SpanElement()..text = 'at isolate start'];
} else if (_isolate.pauseEvent is M.PauseExitEvent) {
children = <Element>[new SpanElement()..text = 'at isolate exit'];
} else if (_isolate.pauseEvent is M.NoneEvent) {
children = <Element>[new SpanElement()..text = 'not yet runnable'];
} else {
final content = <Element>[];
if (_isolate.pauseEvent is M.PauseBreakpointEvent) {
content.add(new SpanElement()..text = 'by breakpoint');
} else if (_isolate.pauseEvent is M.PauseExceptionEvent) {
content.add(new SpanElement()..text = 'by exception');
}
if (M.topFrame(_isolate.pauseEvent) != null) {
content.addAll([
new SpanElement()..text = ' at ',
new FunctionRefElement(
_isolate, M.topFrame(_isolate.pauseEvent).function,
queue: _r.queue)
.element,
new SpanElement()..text = ' (',
new SourceLinkElement(_isolate,
M.topFrame(_isolate.pauseEvent).location, _scripts,
queue: _r.queue)
.element,
new SpanElement()..text = ') '
]);
}
children = content;
}
break;
default:
children = const [];
}
}
void _eventListener(e) {
if (e.isolate.id == _isolate.id) {
_r.dirty();
}
}
}

View file

@ -1,78 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class IsolateRunStateElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateRunStateElement> _r;
Stream<RenderedEvent<IsolateRunStateElement>> get onRendered => _r.onRendered;
M.Isolate _isolate;
M.EventRepository _events;
StreamSubscription _debugSubscription;
StreamSubscription _isolateSubscription;
factory IsolateRunStateElement(M.Isolate isolate, M.EventRepository events,
{RenderingQueue queue}) {
assert(isolate != null);
assert(events != null);
IsolateRunStateElement e = new IsolateRunStateElement.created();
e._r = new RenderingScheduler<IsolateRunStateElement>(e, queue: queue);
e._isolate = isolate;
e._events = events;
return e;
}
IsolateRunStateElement.created() : super.created('isolate-run-state');
@override
void attached() {
super.attached();
_r.enable();
_debugSubscription = _events.onDebugEvent.listen(_eventListener);
_isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_debugSubscription.cancel();
_isolateSubscription.cancel();
}
void render() {
switch (_isolate.status) {
case M.IsolateStatus.loading:
children = <Element>[new SpanElement()..text = 'loading... '];
break;
case M.IsolateStatus.running:
children = <Element>[new SpanElement()..text = 'running '];
break;
case M.IsolateStatus.idle:
children = <Element>[new SpanElement()..text = 'idle '];
break;
case M.IsolateStatus.paused:
children = <Element>[
new SpanElement()
..title = '${_isolate.pauseEvent.timestamp}'
..text = 'paused '
];
break;
}
}
void _eventListener(e) {
if (e.isolate.id == _isolate.id) {
_isolate = e.isolate;
_r.dirty();
}
}
}

View file

@ -1,177 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/utils.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/isolate/counter_chart.dart';
class IsolateSharedSummaryElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateSharedSummaryElement> _r;
Stream<RenderedEvent<IsolateSharedSummaryElement>> get onRendered =>
_r.onRendered;
M.Isolate _isolate;
M.EventRepository _events;
StreamSubscription _isolateSubscription;
factory IsolateSharedSummaryElement(
M.Isolate isolate, M.EventRepository events,
{RenderingQueue queue}) {
assert(isolate != null);
assert(events != null);
IsolateSharedSummaryElement e = new IsolateSharedSummaryElement.created();
e._r = new RenderingScheduler<IsolateSharedSummaryElement>(e, queue: queue);
e._isolate = isolate;
e._events = events;
return e;
}
IsolateSharedSummaryElement.created()
: super.created('isolate-shared-summary');
@override
void attached() {
super.attached();
_r.enable();
_isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_isolateSubscription.cancel();
}
void render() {
final newHeapUsed = Utils.formatSize(_isolate.newSpace.used);
final newHeapCapacity = Utils.formatSize(_isolate.newSpace.capacity);
final oldHeapUsed = Utils.formatSize(_isolate.oldSpace.used);
final oldHeapCapacity = Utils.formatSize(_isolate.oldSpace.capacity);
final content = <Element>[
new DivElement()
..classes = ['menu']
..children = <Element>[
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'new heap',
new DivElement()
..classes = ['memberValue']
..text = '$newHeapUsed of $newHeapCapacity',
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'old heap',
new DivElement()
..classes = ['memberValue']
..text = '$oldHeapUsed of $oldHeapCapacity',
]
],
new BRElement(),
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.debugger(_isolate))
..text = 'debugger'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.classTree(_isolate))
..text = 'class hierarchy'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.cpuProfiler(_isolate))
..text = 'cpu profile'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
..text = 'cpu profile (table)'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.allocationProfiler(_isolate))
..text = 'allocation profile'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.heapSnapshot(_isolate))
..text = 'heap snapshot'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.heapMap(_isolate))..text = 'heap map'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.metrics(_isolate))..text = 'metrics'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.persistentHandles(_isolate))
..text = 'persistent handles'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.ports(_isolate))..text = 'ports'
],
new DivElement()
..children = <Element>[
new SpanElement()..text = 'see ',
new AnchorElement(href: Uris.logging(_isolate))..text = 'logging'
]
],
new IsolateCounterChartElement(_isolate.counters, queue: _r.queue).element
];
if (_isolate.error != null) {
children = <Element>[
new PreElement()
..classes = ['errorBox']
..text = _isolate.error.message,
new DivElement()
..classes = ['summary']
..children = content
];
} else {
children = <Element>[
new DivElement()
..classes = ['summary']
..children = content
];
}
}
void _eventListener(e) {
if (e.isolate.id == _isolate.id) {
_isolate = e.isolate;
_r.dirty();
}
}
}

View file

@ -1,179 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/utils.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/isolate_ref.dart';
import 'package:observatory_2/src/elements/isolate/location.dart';
import 'package:observatory_2/src/elements/isolate/run_state.dart';
class IsolateSummaryElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateSummaryElement> _r;
Stream<RenderedEvent<IsolateSummaryElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.EventRepository _events;
M.IsolateRepository _isolates;
M.ScriptRepository _scripts;
M.Isolate _loadedIsolate;
factory IsolateSummaryElement(
M.IsolateRef isolate,
M.IsolateRepository isolates,
M.EventRepository events,
M.ScriptRepository scripts,
{RenderingQueue queue}) {
assert(isolate != null);
assert(isolates != null);
assert(events != null);
assert(scripts != null);
IsolateSummaryElement e = new IsolateSummaryElement.created();
e._r = new RenderingScheduler<IsolateSummaryElement>(e, queue: queue);
e._isolate = isolate;
e._isolates = isolates;
e._events = events;
e._scripts = scripts;
return e;
}
IsolateSummaryElement.created() : super.created('isolate-summary');
@override
void attached() {
super.attached();
_r.enable();
_load();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
}
void render() {
if (_loadedIsolate == null) {
children = <Element>[
new SpanElement()..text = 'loading ',
new IsolateRefElement(_isolate, _events, queue: _r.queue).element
];
} else {
children = <Element>[
linkAndStatusRow(),
new BRElement(),
memoryRow(),
new BRElement(),
toolsRow(),
];
}
}
Element linkAndStatusRow() {
return new DivElement()
..classes = ['flex-row-wrap']
..children = <Element>[
new DivElement()
..classes = ['isolate-ref-container']
..children = <Element>[
new IsolateRefElement(_isolate, _events, queue: _r.queue).element
],
new DivElement()..style.flex = '1',
new DivElement()
..classes = ['flex-row', 'isolate-state-container']
..children = <Element>[
new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
.element,
new IsolateLocationElement(_isolate, _events, _scripts,
queue: _r.queue)
.element,
new SpanElement()..text = ' [',
new AnchorElement(href: Uris.debugger(_isolate))..text = 'debug',
new SpanElement()..text = ']'
]
];
}
Element memoryRow() {
final isolate = _isolate as M.Isolate;
final newHeapUsed = Utils.formatSize(isolate.newSpace.used);
final newHeapCapacity = Utils.formatSize(isolate.newSpace.capacity);
final oldHeapUsed = Utils.formatSize(isolate.oldSpace.used);
final oldHeapCapacity = Utils.formatSize(isolate.oldSpace.capacity);
final heapUsed =
Utils.formatSize(isolate.newSpace.used + isolate.oldSpace.used);
final heapCapacity =
Utils.formatSize(isolate.newSpace.capacity + isolate.oldSpace.capacity);
return new DivElement()
..classes = ['flex-row-wrap-right']
..children = <Element>[
new DivElement()
..style.padding = '5px'
..text = 'new-space $newHeapUsed of $newHeapCapacity',
new DivElement()
..style.padding = '5px'
..text = '/',
new DivElement()
..style.padding = '5px'
..text = 'old-space $oldHeapUsed of $oldHeapCapacity',
new DivElement()
..style.padding = '5px'
..text = '/',
new DivElement()
..style.padding = '5px'
..text = 'heap $heapUsed of $heapCapacity',
];
}
Element toolsRow() {
return new DivElement()
..classes = ['flex-row-spaced']
..children = <Element>[
new AnchorElement(href: Uris.debugger(_isolate))
..classes = ['flex-item-even']
..text = 'debugger',
new AnchorElement(href: Uris.classTree(_isolate))
..classes = ['flex-item-even']
..text = 'class hierarchy',
new AnchorElement(href: Uris.cpuProfiler(_isolate))
..classes = ['flex-item-even']
..text = 'cpu profile',
new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
..classes = ['flex-item-even']
..text = 'cpu profile (table)',
new AnchorElement(href: Uris.allocationProfiler(_isolate))
..classes = ['flex-item-even']
..text = 'allocation profile',
new AnchorElement(href: Uris.heapSnapshot(_isolate))
..classes = ['flex-item-even']
..text = 'heap snapshot',
new AnchorElement(href: Uris.heapMap(_isolate))
..classes = ['flex-item-even']
..text = 'heap map',
new AnchorElement(href: Uris.metrics(_isolate))
..classes = ['flex-item-even']
..text = 'metrics',
new AnchorElement(href: Uris.persistentHandles(_isolate))
..classes = ['flex-item-even']
..text = 'persistent handles',
new AnchorElement(href: Uris.ports(_isolate))
..classes = ['flex-item-even']
..text = 'ports',
new AnchorElement(href: Uris.logging(_isolate))
..classes = ['flex-item-even']
..text = 'logging',
];
}
Future _load() async {
_loadedIsolate = await _isolates.get(_isolate);
_r.dirty();
}
}

View file

@ -1,108 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library isolate_reconnect_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
class IsolateReconnectElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateReconnectElement> _r;
Stream<RenderedEvent<IsolateReconnectElement>> get onRendered =>
_r.onRendered;
M.VM _vm;
String _missing;
Uri _uri;
M.EventRepository _events;
StreamSubscription _subscription;
M.VM get vm => _vm;
String get missing => _missing;
Uri get uri => _uri;
M.NotificationRepository _notifications;
factory IsolateReconnectElement(M.VM vm, M.EventRepository events,
M.NotificationRepository notifications, String missing, Uri uri,
{RenderingQueue queue}) {
assert(vm != null);
assert(events != null);
assert(missing != null);
assert(uri != null);
assert(notifications != null);
IsolateReconnectElement e = new IsolateReconnectElement.created();
e._r = new RenderingScheduler<IsolateReconnectElement>(e, queue: queue);
e._vm = vm;
e._events = events;
e._missing = missing;
e._uri = uri;
e._notifications = notifications;
return e;
}
IsolateReconnectElement.created() : super.created('isolate-reconnect');
@override
void attached() {
super.attached();
_subscription = _events.onVMUpdate.listen((e) {
_vm = e.vm;
_r.dirty();
});
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_subscription.cancel();
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered']
..children = <Element>[
new HeadingElement.h1()..text = 'Isolate $_missing no longer exists',
new HRElement(),
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = (_vm.isolates.map<Element>((isolate) {
final query = new Map<String, dynamic>.from(_uri.queryParameters);
query['isolateId'] = isolate.id;
final href = new Uri(path: _uri.path, queryParameters: query);
return new DivElement()
..classes = ['memberItem', 'doubleSpaced']
..children = <Element>[
new SpanElement()..text = 'Continue in ',
new AnchorElement(href: '#$href')
..classes = ['isolate-link']
..text = '${isolate.id} (${isolate.name})'
];
}).toList()
..add(new DivElement()
..classes = ['memberItem', 'doubleSpaced']
..children = <Element>[
new SpanElement()..text = 'Go to ',
new AnchorElement(href: Uris.vm())..text = 'isolates summary',
]))
],
];
}
}

View file

@ -1,66 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library isolate_ref_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M show IsolateRef, EventRepository;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class IsolateRefElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateRefElement> _r;
Stream<RenderedEvent<IsolateRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.EventRepository _events;
StreamSubscription _updatesSubscription;
M.IsolateRef get isolate => _isolate;
factory IsolateRefElement(M.IsolateRef isolate, M.EventRepository events,
{RenderingQueue queue}) {
assert(isolate != null);
assert(events != null);
IsolateRefElement e = new IsolateRefElement.created();
e._r = new RenderingScheduler<IsolateRefElement>(e, queue: queue);
e._isolate = isolate;
e._events = events;
return e;
}
IsolateRefElement.created() : super.created('isolate-ref');
@override
void attached() {
super.attached();
_updatesSubscription = _events.onIsolateUpdate
.where((e) => e.isolate.id == isolate.id)
.listen((e) {
_isolate = e.isolate;
_r.dirty();
});
_r.enable();
}
@override
void detached() {
super.detached();
children = <Element>[];
_r.disable(notify: true);
_updatesSubscription.cancel();
}
void render() {
final isolateType = isolate.isSystemIsolate ? 'System Isolate' : 'Isolate';
children = <Element>[
new AnchorElement(href: Uris.inspect(isolate))
..text = '$isolateType ${isolate.number} (${isolate.name})'
..classes = ['isolate-ref']
];
}
}

View file

@ -1,323 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library isolate_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/eval_box.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
import 'package:observatory_2/src/elements/isolate/location.dart';
import 'package:observatory_2/src/elements/isolate/run_state.dart';
import 'package:observatory_2/src/elements/isolate/shared_summary.dart';
import 'package:observatory_2/src/elements/library_ref.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/reload.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/script_inset.dart';
import 'package:observatory_2/src/elements/source_inset.dart';
class IsolateViewElement extends CustomElement implements Renderable {
RenderingScheduler<IsolateViewElement> _r;
Stream<RenderedEvent<IsolateViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.Isolate _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.IsolateRepository _isolates;
M.ScriptRepository _scripts;
M.FunctionRepository _functions;
M.LibraryRepository _libraries;
M.ObjectRepository _objects;
M.EvalRepository _eval;
M.ServiceFunction _function;
M.ScriptRef _rootScript;
StreamSubscription _subscription;
M.VMRef get vm => _vm;
M.Isolate get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
factory IsolateViewElement(
M.VM vm,
M.Isolate isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.IsolateRepository isolates,
M.ScriptRepository scripts,
M.FunctionRepository functions,
M.LibraryRepository libraries,
M.ObjectRepository objects,
M.EvalRepository eval,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(isolates != null);
assert(scripts != null);
assert(functions != null);
assert(objects != null);
assert(eval != null);
assert(libraries != null);
IsolateViewElement e = new IsolateViewElement.created();
e._r = new RenderingScheduler<IsolateViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._isolates = isolates;
e._scripts = scripts;
e._functions = functions;
e._objects = objects;
e._eval = eval;
e._libraries = libraries;
return e;
}
IsolateViewElement.created() : super.created('isolate-view');
@override
attached() {
super.attached();
_r.enable();
_loadExtraData();
_subscription = _events.onIsolateUpdate.listen((e) {
if (e.isolate.id == _isolate) {
_isolate = isolate;
_r.dirty();
}
});
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_subscription.cancel();
}
void render() {
final uptime = new DateTime.now().difference(_isolate.startTime);
final libraries = _isolate.libraries.toList();
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
(new NavReloadElement(_isolate, _isolates, _events, queue: _r.queue)
..onReload.listen((_) async {
_isolate = await _isolates.get(_isolate);
await _loadExtraData();
_r.dirty();
}))
.element,
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_isolate = await _isolates.get(_isolate);
await _loadExtraData();
_r.dirty();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Isolate ${_isolate.name}',
new BRElement(),
new DivElement()
..classes = ['flex-row']
..children = <Element>[
new DivElement()..style.flex = '1',
new DivElement()
..children = <Element>[
new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
.element,
new IsolateLocationElement(_isolate, _events, _scripts,
queue: _r.queue)
.element,
new SpanElement()..text = ' [',
new AnchorElement(href: Uris.debugger(_isolate))
..text = 'debug',
new SpanElement()..text = ']'
]
],
new DivElement()
..children = _function != null
? [
new BRElement(),
(new SourceInsetElement(_isolate, _function.location,
_scripts, _objects, _events,
currentPos: M
.topFrame(isolate.pauseEvent)
.location
.tokenPos,
queue: _r.queue)
..classes = ['header_inset'])
.element
]
: const [],
new HRElement(),
new IsolateSharedSummaryElement(_isolate, _events, queue: _r.queue)
.element,
new HRElement(),
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'started at',
new DivElement()
..classes = ['memberValue']
..text = '${_isolate.startTime}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'uptime',
new DivElement()
..classes = ['memberValue']
..text = '$uptime'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'root library',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
_isolate.rootLibrary == null
? (new SpanElement()..text = 'loading...')
: new LibraryRefElement(
_isolate, _isolate.rootLibrary,
queue: _r.queue)
.element
]
],
new DivElement()
..classes = ['memberItem']
..children = _isolate.entry != null
? [
new DivElement()
..classes = ['memberName']
..text = 'entry',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new FunctionRefElement(_isolate, _isolate.entry,
queue: _r.queue)
.element
]
]
: const [],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'isolate id',
new DivElement()
..classes = ['memberValue']
..text = '${_isolate.number}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'service protocol extensions',
new DivElement()
..classes = ['memberValue']
..text = '${_isolate.extensionRPCs}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'object store',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new AnchorElement(href: Uris.objectStore(_isolate))
..text = 'object store'
]
],
new BRElement(),
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'libraries (${libraries.length})',
new DivElement()
..classes = ['memberValue']
..children = <Element>[
(new CurlyBlockElement(queue: _r.queue)
..content = libraries
.map<Element>((l) => new DivElement()
..children = <Element>[
new LibraryRefElement(_isolate, l,
queue: _r.queue)
.element
])
.toList())
.element
]
],
],
new HRElement(),
new EvalBoxElement(_isolate, _isolate.rootLibrary, _objects, _eval,
queue: _r.queue)
.element,
new DivElement()
..children = _rootScript != null
? [
new HRElement(),
new ScriptInsetElement(
_isolate, _rootScript, _scripts, _objects, _events,
queue: _r.queue)
.element
]
: const [],
]
];
}
Future _loadExtraData() async {
_function = null;
_rootScript = null;
final frame = M.topFrame(_isolate.pauseEvent);
if (frame != null) {
_function = await _functions.get(_isolate, frame.function.id);
}
if (_isolate.rootLibrary != null) {
final rootLibrary =
await _libraries.get(_isolate, _isolate.rootLibrary.id);
_rootScript = rootLibrary.rootScript;
}
_r.dirty();
}
}

View file

@ -1,145 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library json_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
class JSONViewElement extends CustomElement implements Renderable {
RenderingScheduler<JSONViewElement> _r;
Stream<RenderedEvent<JSONViewElement>> get onRendered => _r.onRendered;
M.NotificationRepository _notifications;
Map _map;
M.NotificationRepository get notifications => _notifications;
Map get map => _map;
factory JSONViewElement(Map map, M.NotificationRepository notifications,
{RenderingQueue queue}) {
assert(notifications != null);
assert(map != null);
JSONViewElement e = new JSONViewElement.created();
e._r = new RenderingScheduler<JSONViewElement>(e, queue: queue);
e._notifications = notifications;
e._map = map;
return e;
}
JSONViewElement.created() : super.created('json-view');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Object',
new HRElement(),
new PreElement()..text = JSONPretty.stringify(_map),
]
];
}
}
class JSONPretty {
JSONPretty._();
static String stringify(Map map) => new JSONPretty._()._stringify(map);
String _stringify(Map map) {
_buffer.clear();
_buffer.write('{\n');
_printMap(map, 0);
_buffer.write('}\n');
return _buffer.toString();
}
void _printMap(Map map, int depth) {
if (_seen.contains(map)) {
return;
}
_seen.add(map);
for (var k in map.keys) {
var v = map[k];
if (v is Map) {
_writeIndent(depth);
_buffer.write('"$k": {\n');
_printMap(v, depth + 1);
_writeIndent(depth);
_buffer.write('}\n');
} else if (v is List) {
_writeIndent(depth);
_buffer.write('"$k": [\n');
_printList(v, depth + 1);
_writeIndent(depth);
_buffer.write(']\n');
} else {
_writeIndent(depth);
_buffer.write('"$k": $v');
_buffer.write('\n');
}
}
_seen.remove(map);
}
void _printList(List list, int depth) {
if (_seen.contains(list)) {
return;
}
_seen.add(list);
for (var v in list) {
if (v is Map) {
_writeIndent(depth);
_buffer.write('{\n');
_printMap(v, depth + 1);
_writeIndent(depth);
_buffer.write('}\n');
} else if (v is List) {
_writeIndent(depth);
_buffer.write('[\n');
_printList(v, depth + 1);
_writeIndent(depth);
_buffer.write(']\n');
} else {
_writeIndent(depth);
_buffer.write(v);
_buffer.write('\n');
}
}
_seen.remove(list);
}
void _writeIndent(int depth) {
const tab = ' '; // 2 spaces.
_buffer.write(tab * depth);
}
final _buffer = new StringBuffer();
final _seen = new Set();
}

View file

@ -1,58 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library library_ref_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M show IsolateRef, LibraryRef;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class LibraryRefElement extends CustomElement implements Renderable {
RenderingScheduler<LibraryRefElement> _r;
Stream<RenderedEvent<LibraryRefElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.LibraryRef _library;
M.IsolateRef get isolate => _isolate;
M.LibraryRef get library => _library;
factory LibraryRefElement(M.IsolateRef isolate, M.LibraryRef library,
{RenderingQueue queue}) {
assert(isolate != null);
assert(library != null);
LibraryRefElement e = new LibraryRefElement.created();
e._r = new RenderingScheduler<LibraryRefElement>(e, queue: queue);
e._isolate = isolate;
e._library = library;
return e;
}
LibraryRefElement.created() : super.created('library-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
final name = _library.name;
children = <Element>[
new AnchorElement(href: Uris.inspect(_isolate, object: _library))
..text = (name == null || name.isEmpty) ? 'unnamed' : name
];
}
}

View file

@ -1,330 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library library_view_element;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
import 'package:observatory_2/src/elements/curly_block.dart';
import 'package:observatory_2/src/elements/eval_box.dart';
import 'package:observatory_2/src/elements/field_ref.dart';
import 'package:observatory_2/src/elements/function_ref.dart';
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/library_ref.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/library_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
import 'package:observatory_2/src/elements/script_ref.dart';
import 'package:observatory_2/src/elements/script_inset.dart';
class LibraryViewElement extends CustomElement implements Renderable {
RenderingScheduler<LibraryViewElement> _r;
Stream<RenderedEvent<LibraryViewElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.Library _library;
M.LibraryRepository _libraries;
M.FieldRepository _fields;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ScriptRepository _scripts;
M.ObjectRepository _objects;
M.EvalRepository _eval;
Iterable<M.Field> _variables;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.Library get library => _library;
factory LibraryViewElement(
M.VM vm,
M.IsolateRef isolate,
M.Library library,
M.EventRepository events,
M.NotificationRepository notifications,
M.LibraryRepository libraries,
M.FieldRepository fields,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ScriptRepository scripts,
M.ObjectRepository objects,
M.EvalRepository eval,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(library != null);
assert(libraries != null);
assert(fields != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(scripts != null);
assert(objects != null);
assert(eval != null);
LibraryViewElement e = new LibraryViewElement.created();
e._r = new RenderingScheduler<LibraryViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._library = library;
e._libraries = libraries;
e._fields = fields;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._scripts = scripts;
e._objects = objects;
e._eval = eval;
return e;
}
LibraryViewElement.created() : super.created('library-view');
@override
attached() {
super.attached();
_r.enable();
_refresh();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
final rootScript = library.rootScript;
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
new NavLibraryMenuElement(_isolate, _library, queue: _r.queue).element,
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Library',
new HRElement(),
new ObjectCommonElement(_isolate, _library, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'uri',
new DivElement()
..classes = ['memberValue']
..text = _library.uri
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'vm name',
new DivElement()
..classes = ['memberValue']
..text = _library.vmName
]
],
new HRElement(),
new EvalBoxElement(_isolate, _library, _objects, _eval,
queue: _r.queue)
.element,
new HRElement(),
_createDependencies(),
new BRElement(),
_createScripts(),
new BRElement(),
_createClasses(),
new BRElement(),
_createVariables(),
new BRElement(),
_createFunctions(),
if (rootScript != null) ...[
new HRElement(),
new ScriptInsetElement(
_isolate, rootScript, _scripts, _objects, _events,
queue: _r.queue)
.element
],
]
];
}
Future _refresh() async {
_library = await _libraries.get(_isolate, _library.id);
_variables = null;
_r.dirty();
_variables = await Future.wait(
_library.variables.map((field) => _fields.get(_isolate, field.id)));
_r.dirty();
}
Element _createDependencies() {
if (_library.dependencies.isEmpty) {
return new SpanElement();
}
final dependencies = _library.dependencies.toList();
return new DivElement()
..children = <Element>[
new SpanElement()..text = 'dependencies (${dependencies.length}) ',
(new CurlyBlockElement(queue: _r.queue)
..content = dependencies
.map<Element>((d) => new DivElement()
..classes = ['indent']
..children = <Element>[
new SpanElement()
..text = d.isImport ? 'import ' : 'export ',
new LibraryRefElement(_isolate, d.target, queue: _r.queue)
.element,
new SpanElement()
..text = d.prefix == null ? '' : ' as ${d.prefix}',
new SpanElement()..text = d.isDeferred ? ' deferred' : '',
])
.toList())
.element
];
}
Element _createScripts() {
if (_library.scripts.isEmpty) {
return new SpanElement();
}
final scripts = _library.scripts.toList();
return new DivElement()
..children = <Element>[
new SpanElement()..text = 'scripts (${scripts.length}) ',
(new CurlyBlockElement(queue: _r.queue)
..content = scripts
.map<Element>((s) => new DivElement()
..classes = ['indent']
..children = <Element>[
new ScriptRefElement(_isolate, s, queue: _r.queue).element
])
.toList())
.element
];
}
Element _createClasses() {
if (_library.classes.isEmpty) {
return new SpanElement();
}
final classes = _library.classes.toList();
return new DivElement()
..children = <Element>[
new SpanElement()..text = 'classes (${classes.length}) ',
(new CurlyBlockElement(queue: _r.queue)
..content = classes
.map<Element>((c) => new DivElement()
..classes = ['indent']
..children = <Element>[
new ClassRefElement(_isolate, c, queue: _r.queue).element
])
.toList())
.element
];
}
Element _createVariables() {
if (_library.variables.isEmpty) {
return new SpanElement();
}
final variables = _library.variables.toList();
return new DivElement()
..children = <Element>[
new SpanElement()..text = 'variables (${variables.length}) ',
(new CurlyBlockElement(queue: _r.queue)
..content = <Element>[
_variables == null
? (new SpanElement()..text = 'loading...')
: (new DivElement()
..classes = ['indent', 'memberList']
..children = _variables
.map<Element>((f) => new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..children = <Element>[
new FieldRefElement(_isolate, f, _objects,
queue: _r.queue)
.element
],
new DivElement()
..classes = ['memberValue']
..children = <Element>[
new SpanElement()..text = ' = ',
anyRef(_isolate, f.staticValue, _objects,
queue: _r.queue)
]
])
.toList())
])
.element
];
}
Element _createFunctions() {
if (_library.functions.isEmpty) {
return new SpanElement();
}
final functions = _library.functions.toList();
return new DivElement()
..children = <Element>[
new SpanElement()..text = 'functions (${functions.length}) ',
(new CurlyBlockElement(queue: _r.queue)
..content = functions
.map<Element>((f) => new DivElement()
..classes = ['indent']
..children = <Element>[
new FunctionRefElement(_isolate, f, queue: _r.queue)
.element
])
.toList())
.element
];
}
}

View file

@ -1,64 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M
show IsolateRef, LocalVarDescriptorsRef;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class LocalVarDescriptorsRefElement extends CustomElement
implements Renderable {
RenderingScheduler<LocalVarDescriptorsRefElement> _r;
Stream<RenderedEvent<LocalVarDescriptorsRefElement>> get onRendered =>
_r.onRendered;
M.IsolateRef _isolate;
M.LocalVarDescriptorsRef _localVar;
M.IsolateRef get isolate => _isolate;
M.LocalVarDescriptorsRef get localVar => _localVar;
factory LocalVarDescriptorsRefElement(
M.IsolateRef isolate, M.LocalVarDescriptorsRef localVar,
{RenderingQueue queue}) {
assert(isolate != null);
assert(localVar != null);
LocalVarDescriptorsRefElement e =
new LocalVarDescriptorsRefElement.created();
e._r =
new RenderingScheduler<LocalVarDescriptorsRefElement>(e, queue: queue);
e._isolate = isolate;
e._localVar = localVar;
return e;
}
LocalVarDescriptorsRefElement.created() : super.created('var-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
final text = (_localVar.name == null || _localVar.name == '')
? 'LocalVarDescriptors'
: _localVar.name;
children = <Element>[
new AnchorElement(href: Uris.inspect(_isolate, object: _localVar))
..text = text
];
}
}

View file

@ -1,113 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library logging_page;
import 'dart:async';
import 'dart:html';
import 'package:logging/logging.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/logging_list.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
class LoggingPageElement extends CustomElement implements Renderable {
RenderingScheduler<LoggingPageElement> _r;
Stream<RenderedEvent<LoggingPageElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
Level _level = Level.ALL;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
factory LoggingPageElement(M.VM vm, M.IsolateRef isolate,
M.EventRepository events, M.NotificationRepository notifications,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
LoggingPageElement e = new LoggingPageElement.created();
e._r = new RenderingScheduler<LoggingPageElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
return e;
}
LoggingPageElement.created() : super.created('logging-page');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
LoggingListElement _logs;
void render() {
_logs = _logs ?? new LoggingListElement(_isolate, _events);
_logs.level = _level;
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('logging'),
(new NavRefreshElement(label: 'clear', queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_logs = null;
_r.dirty();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Logging',
new SpanElement()..text = 'Show messages with severity ',
_createLevelSelector(),
new HRElement(),
_logs.element
]
];
}
Element _createLevelSelector() {
var s = new SelectElement()
..value = _level.name
..children = Level.LEVELS.map((level) {
return new OptionElement(value: level.name, selected: _level == level)
..text = level.name;
}).toList(growable: false);
s.onChange.listen((_) {
_level = Level.LEVELS[s.selectedIndex];
_r.dirty();
});
return s;
}
}

View file

@ -1,84 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'package:logging/logging.dart';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/utils.dart';
class LoggingListElement extends CustomElement implements Renderable {
RenderingScheduler<LoggingListElement> _r;
Stream<RenderedEvent<LoggingListElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.EventRepository _events;
StreamSubscription _subscription;
Level _level = Level.ALL;
final _logs = <Map>[];
M.IsolateRef get isolate => _isolate;
Level get level => _level;
set level(Level value) => _level = _r.checkAndReact(_level, value);
factory LoggingListElement(M.IsolateRef isolate, M.EventRepository events,
{RenderingQueue queue}) {
assert(isolate != null);
assert(events != null);
LoggingListElement e = new LoggingListElement.created();
e._r = new RenderingScheduler<LoggingListElement>(e, queue: queue);
e._isolate = isolate;
e._events = events;
return e;
}
LoggingListElement.created() : super.created('logging-list');
@override
attached() {
super.attached();
_r.enable();
_subscription = _events.onLoggingEvent.listen((e) {
if (e.isolate.id == _isolate.id) {
_logs.add(e.logRecord);
if (_shouldBeVisible(_logs.last)) {
_r.dirty();
}
}
});
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_subscription.cancel();
}
void render() {
children = _logs
.where(_shouldBeVisible)
.map<Element>((logRecord) => new DivElement()
..classes = ['logItem', logRecord['level'].name]
..children = <Element>[
new SpanElement()
..classes = ['level']
..text = logRecord['level'].name,
new SpanElement()
..classes = ['time']
..text = Utils.formatDateTime(logRecord['time']),
new SpanElement()
..classes = ['message']
..text = logRecord["message"].valueAsString
])
.toList();
}
bool _shouldBeVisible(Map record) => _level.compareTo(record['level']) <= 0;
}

View file

@ -1,63 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M
show IsolateRef, MegamorphicCacheRef;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/helpers/uris.dart';
class MegamorphicCacheRefElement extends CustomElement implements Renderable {
RenderingScheduler<MegamorphicCacheRefElement> _r;
Stream<RenderedEvent<MegamorphicCacheRefElement>> get onRendered =>
_r.onRendered;
M.IsolateRef _isolate;
M.MegamorphicCacheRef _cache;
M.IsolateRef get isolate => _isolate;
M.MegamorphicCacheRef get cache => _cache;
factory MegamorphicCacheRefElement(
M.IsolateRef isolate, M.MegamorphicCacheRef cache,
{RenderingQueue queue}) {
assert(isolate != null);
assert(cache != null);
MegamorphicCacheRefElement e = new MegamorphicCacheRefElement.created();
e._r = new RenderingScheduler<MegamorphicCacheRefElement>(e, queue: queue);
e._isolate = isolate;
e._cache = cache;
return e;
}
MegamorphicCacheRefElement.created() : super.created('megamorphic-cache-ref');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
new AnchorElement(href: Uris.inspect(_isolate, object: _cache))
..children = <Element>[
new SpanElement()
..classes = ['emphasize']
..text = 'MegamorphicCache',
new SpanElement()..text = ' (${_cache.selector})'
]
];
}
}

View file

@ -1,180 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library megamorphiccache_view;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
import 'package:observatory_2/src/elements/object_common.dart';
class MegamorphicCacheViewElement extends CustomElement implements Renderable {
RenderingScheduler<MegamorphicCacheViewElement> _r;
Stream<RenderedEvent<MegamorphicCacheViewElement>> get onRendered =>
_r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.MegamorphicCache _cache;
M.MegamorphicCacheRepository _caches;
M.RetainedSizeRepository _retainedSizes;
M.ReachableSizeRepository _reachableSizes;
M.InboundReferencesRepository _references;
M.RetainingPathRepository _retainingPaths;
M.ObjectRepository _objects;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
M.MegamorphicCache get cache => _cache;
factory MegamorphicCacheViewElement(
M.VM vm,
M.IsolateRef isolate,
M.MegamorphicCache cache,
M.EventRepository events,
M.NotificationRepository notifications,
M.MegamorphicCacheRepository caches,
M.RetainedSizeRepository retainedSizes,
M.ReachableSizeRepository reachableSizes,
M.InboundReferencesRepository references,
M.RetainingPathRepository retainingPaths,
M.ObjectRepository objects,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
assert(cache != null);
assert(caches != null);
assert(retainedSizes != null);
assert(reachableSizes != null);
assert(references != null);
assert(retainingPaths != null);
assert(objects != null);
MegamorphicCacheViewElement e = new MegamorphicCacheViewElement.created();
e._r = new RenderingScheduler<MegamorphicCacheViewElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._cache = cache;
e._caches = caches;
e._retainedSizes = retainedSizes;
e._reachableSizes = reachableSizes;
e._references = references;
e._retainingPaths = retainingPaths;
e._objects = objects;
return e;
}
MegamorphicCacheViewElement.created()
: super.created('megamorphiccache-view');
@override
attached() {
super.attached();
_r.enable();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('megamorphic inline cache'),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) async {
e.element.disabled = true;
_cache = await _caches.get(_isolate, _cache.id);
_r.dirty();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Megamorphic Cache',
new HRElement(),
new ObjectCommonElement(_isolate, _cache, _retainedSizes,
_reachableSizes, _references, _retainingPaths, _objects,
queue: _r.queue)
.element,
new BRElement(),
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'selector',
new DivElement()
..classes = ['memberName']
..text = '${_cache.selector}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'mask',
new DivElement()
..classes = ['memberName']
..text = '${_cache.mask}'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'buckets',
new DivElement()
..classes = ['memberName']
..children = <Element>[
anyRef(_isolate, _cache.buckets, _objects,
queue: _r.queue)
]
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'argumentsDescriptor',
new DivElement()
..classes = ['memberName']
..children = <Element>[
anyRef(_isolate, _cache.argumentsDescriptor, _objects,
queue: _r.queue)
]
]
],
]
];
}
}

View file

@ -1,168 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class MetricDetailsElement extends CustomElement implements Renderable {
RenderingScheduler<MetricDetailsElement> _r;
Stream<RenderedEvent<MetricDetailsElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.Metric _metric;
M.MetricRepository _metrics;
M.IsolateRef get isolate => _isolate;
M.Metric get metric => _metric;
factory MetricDetailsElement(
M.IsolateRef isolate, M.Metric metric, M.MetricRepository metrics,
{RenderingQueue queue}) {
assert(isolate != null);
assert(metric != null);
assert(metrics != null);
MetricDetailsElement e = new MetricDetailsElement.created();
e._r = new RenderingScheduler<MetricDetailsElement>(e, queue: queue);
e._isolate = isolate;
e._metric = metric;
e._metrics = metrics;
return e;
}
MetricDetailsElement.created() : super.created('metric-details');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'name',
new DivElement()
..classes = ['memberValue']
..text = _metric.name,
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'description',
new DivElement()
..classes = ['memberValue']
..text = _metric.description,
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'refresh rate',
new DivElement()
..classes = ['memberValue']
..children = _createRefreshRateSelect(),
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'buffer size',
new DivElement()
..classes = ['memberValue']
..children = _createBufferSizeSelect(),
]
]
];
}
List<Element> _createRefreshRateSelect() {
final current = _metrics.getSamplingRate(_isolate, _metric);
var s;
return [
s = new SelectElement()
..value = _rateToString(current)
..children = M.MetricSamplingRate.values.map((rate) {
return new OptionElement(
value: _rateToString(current), selected: current == rate)
..text = _rateToString(rate);
}).toList(growable: false)
..onChange.listen((_) {
_metrics.setSamplingRate(
_isolate, _metric, M.MetricSamplingRate.values[s.selectedIndex]);
_r.dirty();
})
];
}
List<Element> _createBufferSizeSelect() {
final current = _metrics.getBufferSize(_isolate, _metric);
var s;
return [
s = new SelectElement()
..value = _sizeToString(current)
..children = M.MetricBufferSize.values.map((rate) {
return new OptionElement(
value: _sizeToString(current), selected: current == rate)
..text = _sizeToString(rate);
}).toList(growable: false)
..onChange.listen((_) {
_metrics.setBufferSize(
_isolate, _metric, M.MetricBufferSize.values[s.selectedIndex]);
_r.dirty();
})
];
}
static String _rateToString(M.MetricSamplingRate rate) {
switch (rate) {
case M.MetricSamplingRate.off:
return 'Never';
case M.MetricSamplingRate.e100ms:
return 'Ten times per second';
case M.MetricSamplingRate.e1s:
return 'Once a second';
case M.MetricSamplingRate.e2s:
return 'Every two seconds';
case M.MetricSamplingRate.e4s:
return 'Every four seconds';
case M.MetricSamplingRate.e8s:
return 'Every eight seconds';
}
throw new Exception('Unknown MetricSamplingRate ($rate)');
}
static String _sizeToString(M.MetricBufferSize size) {
switch (size) {
case M.MetricBufferSize.n10samples:
return '10';
case M.MetricBufferSize.n100samples:
return '100';
case M.MetricBufferSize.n1000samples:
return '1000';
}
throw new Exception('Unknown MetricSamplingRate ($size)');
}
}

View file

@ -1,117 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
class MetricGraphElement extends CustomElement implements Renderable {
RenderingScheduler<MetricGraphElement> _r;
Stream<RenderedEvent<MetricGraphElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.Metric _metric;
M.MetricRepository _metrics;
Timer _timer;
M.IsolateRef get isolate => _isolate;
M.Metric get metric => _metric;
factory MetricGraphElement(
M.IsolateRef isolate, M.Metric metric, M.MetricRepository metrics,
{RenderingQueue queue}) {
assert(isolate != null);
assert(metric != null);
assert(metrics != null);
MetricGraphElement e = new MetricGraphElement.created();
e._r = new RenderingScheduler<MetricGraphElement>(e, queue: queue);
e._isolate = isolate;
e._metric = metric;
e._metrics = metrics;
return e;
}
MetricGraphElement.created() : super.created('metric-graph');
@override
void attached() {
super.attached();
_r.enable();
_timer = new Timer.periodic(const Duration(seconds: 1), (_) => _r.dirty());
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_timer.cancel();
}
void render() {
final min = _metrics.getMinValue(_isolate, _metric);
final max = _metrics.getMaxValue(_isolate, _metric);
final rows = _metrics
.getSamples(_isolate, _metric)
.map((s) => [s.time.millisecondsSinceEpoch, s.value])
.toList();
final current = rows.last.last;
var message = 'current: $current';
if (min != null) {
message = 'min: $min, $message';
}
if (max != null) {
message = message + ', max: $max';
}
final host = new DivElement();
children = <Element>[
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = min == null
? const []
: [
new DivElement()
..classes = ['memberName']
..text = 'min',
new DivElement()
..classes = ['memberValue']
..text = '$min'
],
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'current',
new DivElement()
..classes = ['memberValue']
..text = '$current'
],
new DivElement()
..classes = ['memberItem']
..children = max == null
? const []
: [
new DivElement()
..classes = ['memberName']
..text = 'max',
new DivElement()
..classes = ['memberValue']
..text = '$max'
]
],
];
if (rows.length <= 1) {
return;
}
}
}

View file

@ -1,159 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library metrics;
import 'dart:async';
import 'dart:html';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/metric/details.dart';
import 'package:observatory_2/src/elements/metric/graph.dart';
import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
import 'package:observatory_2/src/elements/nav/notify.dart';
import 'package:observatory_2/src/elements/nav/refresh.dart';
import 'package:observatory_2/src/elements/nav/top_menu.dart';
import 'package:observatory_2/src/elements/nav/vm_menu.dart';
class MetricsPageElement extends CustomElement implements Renderable {
RenderingScheduler<MetricsPageElement> _r;
Stream<RenderedEvent<MetricsPageElement>> get onRendered => _r.onRendered;
M.VM _vm;
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
M.MetricRepository _metrics;
List<M.Metric> _available;
M.Metric _selected;
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
factory MetricsPageElement(
M.VM vm,
M.IsolateRef isolate,
M.EventRepository events,
M.NotificationRepository notifications,
M.MetricRepository metrics,
{RenderingQueue queue}) {
assert(vm != null);
assert(isolate != null);
assert(events != null);
assert(notifications != null);
MetricsPageElement e = new MetricsPageElement.created();
e._r = new RenderingScheduler<MetricsPageElement>(e, queue: queue);
e._vm = vm;
e._isolate = isolate;
e._events = events;
e._notifications = notifications;
e._metrics = metrics;
return e;
}
MetricsPageElement.created() : super.created('metrics-page');
@override
attached() {
super.attached();
_r.enable();
_refresh();
}
@override
detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
}
void render() {
children = <Element>[
navBar(<Element>[
new NavTopMenuElement(queue: _r.queue).element,
new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
navMenu('metrics'),
(new NavRefreshElement(queue: _r.queue)
..onRefresh.listen((e) {
e.element.disabled = true;
_refresh();
}))
.element,
new NavNotifyElement(_notifications, queue: _r.queue).element
]),
new DivElement()
..classes = ['content-centered-big']
..children = <Element>[
new HeadingElement.h2()..text = 'Metrics',
new HRElement(),
new DivElement()
..classes = ['memberList']
..children = <Element>[
new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'Metric',
new DivElement()
..classes = ['memberValue']
..children = _available == null
? [new SpanElement()..text = 'Loading..']
: _createMetricSelect()
]
],
new HRElement(),
new DivElement()
..children = _selected == null
? const []
: [
new MetricDetailsElement(_isolate, _selected, _metrics,
queue: _r.queue)
.element
],
new HRElement(),
new DivElement()
..classes = ['graph']
..children = _selected == null
? const []
: [
new MetricGraphElement(_isolate, _selected, _metrics,
queue: _r.queue)
.element
]
],
];
}
Future _refresh() async {
_available = (await _metrics.list(_isolate)).toList();
if (!_available.contains(_selected)) {
_selected = _available.first;
}
_r.dirty();
}
List<Element> _createMetricSelect() {
var s;
return [
s = new SelectElement()
..value = _selected.name
..children = _available.map((metric) {
return new OptionElement(
value: metric.name, selected: _selected == metric)
..text = metric.name;
}).toList(growable: false)
..onChange.listen((_) {
_selected = _available[s.selectedIndex];
_r.dirty();
})
];
}
}

Some files were not shown because too many files have changed in this diff Show more