List scripts in library and display script source

BUG=
R=iposva@google.com

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@30732 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
johnmccutchan@google.com 2013-11-27 19:54:52 +00:00
parent 730ee1d1f8
commit 589ea683c3
21 changed files with 2894 additions and 1294 deletions

View file

@ -13,9 +13,12 @@ main() {
compileToJs(_) {
print("Running dart2js");
var dart_path = Platform.executable;
var bin_path = dart_path.substring(0, dart_path.lastIndexOf(Platform.pathSeparator));
var dart2js_path = "$bin_path${Platform.pathSeparator}dart2js";
var dart_path = Platform.executable;
var dart2js_path = 'dart2js';
if (dart_path.lastIndexOf(Platform.pathSeparator) != -1) {
var bin_path = dart_path.substring(0, dart_path.lastIndexOf(Platform.pathSeparator));
dart2js_path = "$bin_path${Platform.pathSeparator}dart2js";
}
var result =
Process.runSync(dart2js_path,
[ '--minify', '-o', 'out/web/index.html_bootstrap.dart.js',

View file

@ -108,7 +108,8 @@
</div>
</template>
</polymer-element><polymer-element name="disassembly-entry" extends="observatory-element">
</polymer-element>
<polymer-element name="disassembly-entry" extends="observatory-element">
<template>
<div class="row">
<template if="{{ instruction['type'] == 'DisassembledInstructionComment' }}">
@ -260,7 +261,7 @@
<template>
<div class="row">
<div class="col-md-1">
<img src="packages/observatory/src/observatory_elements/img/isolate_icon.png" class="img-polaroid">
<img src="img/isolate_icon.png" class="img-polaroid">
</div>
<div class="col-md-1">{{ isolate }}</div>
<div class="col-md-10">{{ name }}</div>
@ -317,9 +318,23 @@
</template>
</template>
</polymer-element><polymer-element name="library-view" extends="observatory-element">
</polymer-element>
<polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
<div class="alert alert-info">Scripts</div>
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ script in library['scripts']}}">
<td>
{{ script['kind'] }}
</td>
<td>
<a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
</td>
</tr>
</tbody>
</table>
<div class="alert alert-info">Imported Libraries</div>
<table class="table table-hover">
<tbody>
@ -403,6 +418,29 @@
</tr>
</tbody>
</table>
</template>
</polymer-element><polymer-element name="source-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel-heading">{{ source.url }}</div>
<div class="panel-body">
<div class="row">
<div><strong>Source</strong></div>
</div>
<pre> <template repeat="{{ line in source.lines }}">{{line.paddedLine}} {{line.src}}
</template>
</pre>
</div>
</div>
</div>
</template>
</polymer-element><polymer-element name="script-view" extends="observatory-element">
<template>
<source-view app="{{ app }}" source="{{ script['source'] }}"></source-view>
</template>
</polymer-element><polymer-element name="stack-trace" extends="observatory-element">
@ -461,6 +499,9 @@
<template if="{{ messageType == 'Code' }}">
<code-view app="{{ app }}" code="{{ message }}"></code-view>
</template>
<template if="{{ messageType == 'Script' }}">
<script-view app="{{ app }}" script="{{ message }}"></script-view>
</template>
<!-- Add new views and message types in the future here. -->
</template>
@ -495,4 +536,4 @@
</polymer-element>
<observatory-application></observatory-application>
</body></html>
</body></html>

View file

@ -14,12 +14,14 @@ import 'package:observatory/src/observatory_elements/isolate_summary.dart' as i8
import 'package:observatory/src/observatory_elements/isolate_list.dart' as i9;
import 'package:observatory/src/observatory_elements/json_view.dart' as i10;
import 'package:observatory/src/observatory_elements/library_view.dart' as i11;
import 'package:observatory/src/observatory_elements/stack_trace.dart' as i12;
import 'package:observatory/src/observatory_elements/message_viewer.dart' as i13;
import 'package:observatory/src/observatory_elements/navigation_bar.dart' as i14;
import 'package:observatory/src/observatory_elements/response_viewer.dart' as i15;
import 'package:observatory/src/observatory_elements/observatory_application.dart' as i16;
import 'index.html.0.dart' as i17;
import 'package:observatory/src/observatory_elements/source_view.dart' as i12;
import 'package:observatory/src/observatory_elements/script_view.dart' as i13;
import 'package:observatory/src/observatory_elements/stack_trace.dart' as i14;
import 'package:observatory/src/observatory_elements/message_viewer.dart' as i15;
import 'package:observatory/src/observatory_elements/navigation_bar.dart' as i16;
import 'package:observatory/src/observatory_elements/response_viewer.dart' as i17;
import 'package:observatory/src/observatory_elements/observatory_application.dart' as i18;
import 'index.html.0.dart_modified.dart' as i19;
void main() {
configureForDeployment([
@ -35,12 +37,14 @@ void main() {
'package:observatory/src/observatory_elements/isolate_list.dart',
'package:observatory/src/observatory_elements/json_view.dart',
'package:observatory/src/observatory_elements/library_view.dart',
'package:observatory/src/observatory_elements/source_view.dart',
'package:observatory/src/observatory_elements/script_view.dart',
'package:observatory/src/observatory_elements/stack_trace.dart',
'package:observatory/src/observatory_elements/message_viewer.dart',
'package:observatory/src/observatory_elements/navigation_bar.dart',
'package:observatory/src/observatory_elements/response_viewer.dart',
'package:observatory/src/observatory_elements/observatory_application.dart',
'index.html.0.dart',
'index.html.0.dart_modified.dart',
]);
i17.main();
i19.polymerMainWrapper();
}

View file

@ -11,3 +11,4 @@ part 'src/observatory/application.dart';
part 'src/observatory/isolate.dart';
part 'src/observatory/isolate_manager.dart';
part 'src/observatory/request_manager.dart';
part 'src/observatory/script_source.dart';

View file

@ -12,4 +12,6 @@ export 'package:observatory/src/observatory_elements/navigation_bar.dart';
export
'package:observatory/src/observatory_elements/observatory_application.dart';
export 'package:observatory/src/observatory_elements/response_viewer.dart';
export 'package:observatory/src/observatory_elements/stack_trace.dart';
export 'package:observatory/src/observatory_elements/script_view.dart';
export 'package:observatory/src/observatory_elements/source_view.dart';
export 'package:observatory/src/observatory_elements/stack_trace.dart';

View file

@ -15,9 +15,11 @@
<link rel="import" href="src/observatory_elements/navigation_bar.html">
<link rel="import"
href="src/observatory_elements/observatory_application.html">
<link rel="import"
href="src/observatory_elements/observatory_element.html">
<link rel="import"
href="src/observatory_elements/observatory_element.html">
<link rel="import" href="src/observatory_elements/response_viewer.html">
<link rel="import" href="src/observatory_elements/script_view.html">
<link rel="import" href="src/observatory_elements/source_view.html">
<link rel="import" href="src/observatory_elements/stack_trace.html">
</head>
</html>

View file

@ -6,8 +6,10 @@ part of observatory;
/// State for a running isolate.
class Isolate extends Observable {
@observable final int id;
@observable final String name;
@observable int id;
@observable String name;
@observable final Map<String, ScriptSource> scripts =
toObservable(new Map<String, ScriptSource>());
Isolate(this.id, this.name);

View file

@ -24,6 +24,15 @@ class IsolateManager extends Observable {
});
}
Isolate getIsolate(int id) {
Isolate isolate = isolates[id];
if (isolate == null) {
isolate = new Isolate(id, '');
isolates[id] = isolate;
}
return isolate;
}
void _updateIsolates(List<Map> members) {
// Find dead isolates.
var deadIsolates = [];
@ -43,6 +52,8 @@ class IsolateManager extends Observable {
if (isolates[id] == null) {
var isolate = new Isolate(id, name);
isolates[id] = isolate;
} else {
isolates[id].name = name;
}
});
}

View file

@ -16,7 +16,7 @@ class LocationManager extends Observable {
ObservatoryApplication get application => _application;
@observable String currentHash = '';
@observable Uri currentHashUri;
void init() {
window.onHashChange.listen((event) {
if (setDefaultHash()) {
@ -48,6 +48,15 @@ class LocationManager extends Observable {
return currentIsolateAnchorPrefix() != null;
}
bool get isScriptLink {
String type = currentHashUri.queryParameters['type'];
return type == 'Script';
}
String get scriptName {
return Uri.decodeQueryComponent(currentHashUri.queryParameters['name']);
}
/// Extract the current isolate id as an integer. Returns [InvalidIsolateId]
/// if none is present in window.location.
int currentIsolateId() {
@ -76,6 +85,7 @@ class LocationManager extends Observable {
currentHash = window.location.hash;
// Chomp off the #
String requestUrl = currentHash.substring(1);
currentHashUri = Uri.parse(requestUrl);
application.requestManager.get(requestUrl);
}
@ -109,6 +119,16 @@ class LocationManager extends Observable {
return classLink(isolateId, cid);
}
/// Create a request for the script [objectId] with script [name].
@observable
String currentIsolateScriptLink(int objectId, String name) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return scriptLink(isolateId, objectId, name);
}
/// Create a request for [l] on [isolateId].
@observable
String relativeLink(int isolateId, String l) {
@ -126,4 +146,12 @@ class LocationManager extends Observable {
String classLink(int isolateId, int cid) {
return '#/isolates/$isolateId/classes/$cid';
}
@observable
/// Create a request for the script [objectId] with script [url].
String scriptLink(int isolateId, int objectId, String name) {
String encodedName = Uri.encodeQueryComponent(name);
return '#/isolates/$isolateId/objects/$objectId'
'?type=Script&name=$encodedName';
}
}

View file

@ -47,11 +47,47 @@ abstract class RequestManager extends Observable {
/// Request [requestString] from the VM service. Updates [responses].
/// Will trigger [interceptor] if one is set.
Future<Map> get(String requestString) {
request(requestString).then((responseString) {
parseResponses(responseString);
void get(String requestString) {
if (_application.locationManager.isScriptLink) {
// We cache script sources.
String scriptName = _application.locationManager.scriptName;
getScriptSource(scriptName, requestString).then((source) {
if (source != null) {
setResponses([{
'type': 'Script',
'source': source
}]);
} else {
setResponses([{
'type': 'RequestError',
'error': 'Source for $scriptName could not be loaded.'
}]);
}
});
} else {
request(requestString).then((responseString) {
parseResponses(responseString);
}).catchError((e) {
setResponseError(e.target);
});
}
}
Future<ScriptSource> getScriptSource(String name, String requestString) {
int isolateId = _application.locationManager.currentIsolateId();
Isolate isolate = _application.isolateManager.getIsolate(isolateId);
ScriptSource source = isolate.scripts[name];
if (source != null) {
return new Future.value(source);
}
return request(requestString).then((responseString) {
var r = JSON.decode(responseString);
ScriptSource scriptSource = new ScriptSource(r);
isolate.scripts[name] = scriptSource;
return scriptSource;
}).catchError((e) {
setResponseError(e.target);
return null;
});
}

View file

@ -0,0 +1,42 @@
// 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 observatory;
class ScriptSourceLine extends Observable {
final int line;
final int numDigits;
@observable final String src;
@observable String paddedLine;
ScriptSourceLine(this.line, this.numDigits, this.src) {
paddedLine = '$line';
for (int i = paddedLine.length; i < numDigits; i++) {
paddedLine = ' $paddedLine';
}
}
}
class ScriptSource extends Observable {
@observable String kind = '';
@observable String url = '';
@observable List<ScriptSourceLine> lines = toObservable([]);
ScriptSource(Map response) {
kind = response['kind'];
url = response['name'];
buildSourceLines(response['source']);
}
void buildSourceLines(String src) {
List<String> splitSrc = src.split('\n');
int numDigits = '${splitSrc.length+1}'.length;
for (int i = 0; i < splitSrc.length; i++) {
ScriptSourceLine sourceLine = new ScriptSourceLine(i+1, numDigits,
splitSrc[i]);
lines.add(sourceLine);
}
}
String toString() => 'ScriptSource';
}

View file

@ -4,6 +4,19 @@
<polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
<div class="alert alert-info">Scripts</div>
<table class="table table-hover">
<tbody>
<tr template repeat="{{ script in library['scripts']}}">
<td>
{{ script['kind'] }}
</td>
<td>
<a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
</td>
</tr>
</tbody>
</table>
<div class="alert alert-info">Imported Libraries</div>
<table class="table table-hover">
<tbody>
@ -87,6 +100,7 @@
</tr>
</tbody>
</table>
</template>
<script type="application/dart" src="library_view.dart"></script>
</polymer-element>

View file

@ -7,6 +7,8 @@
<link rel="import" href="isolate_list.html">
<link rel="import" href="library_view.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="script_view.html">
<link rel="import" href="source_view.html">
<link rel="import" href="stack_trace.html">
</head>
<polymer-element name="message-viewer" extends="observatory-element">
@ -42,6 +44,9 @@
<template if="{{ messageType == 'Code' }}">
<code-view app="{{ app }}" code="{{ message }}"></code-view>
</template>
<template if="{{ messageType == 'Script' }}">
<script-view app="{{ app }}" script="{{ message }}"></script-view>
</template>
<!-- Add new views and message types in the future here. -->
</template>
<script type="application/dart" src="message_viewer.dart"></script>

View file

@ -0,0 +1,16 @@
// 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 script_view_element;
import 'package:polymer/polymer.dart';
import 'observatory_element.dart';
/// Displays an Error response.
@CustomTag('script-view')
class ScriptViewElement extends ObservatoryElement {
@published Map script;
ScriptViewElement.created() : super.created();
}

View file

@ -0,0 +1,10 @@
<head>
<link rel="import" href="observatory_element.html">
<link rel="import" href="source_view.html">
</head>
<polymer-element name="script-view" extends="observatory-element">
<template>
<source-view app="{{ app }}" source="{{ script['source'] }}"></source-view>
</template>
<script type="application/dart" src="script_view.dart"></script>
</polymer-element>

View file

@ -0,0 +1,17 @@
// 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 source_view_element;
import 'package:polymer/polymer.dart';
import 'package:observatory/observatory.dart';
import 'observatory_element.dart';
/// Displays an Error response.
@CustomTag('source-view')
class SourceViewElement extends ObservatoryElement {
@published ScriptSource source;
SourceViewElement.created() : super.created();
}

View file

@ -0,0 +1,22 @@
<head>
<link rel="import" href="observatory_element.html">
</head>
<polymer-element name="source-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel-heading">{{ source.url }}</div>
<div class="panel-body">
<div class="row">
<div><strong>Source</strong></div>
</div>
<pre>
<template repeat="{{ line in source.lines }}">{{line.paddedLine}} {{line.src}}
</template>
</pre>
</div>
</div>
</div>
</template>
<script type="application/dart" src="source_view.dart"></script>
</polymer-element>

View file

@ -5,7 +5,7 @@
<link type="text/css" rel="stylesheet"
href="bootstrap_css/css/bootstrap.min.css" />
<link rel="import" href="packages/observatory/observatory_elements.html">
<script type='application/dart'>export 'package:polymer/init.dart';</script>
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>

View file

@ -6791,6 +6791,24 @@ RawString* Script::GenerateSource() const {
}
const char* Script::GetKindAsCString() const {
switch (kind()) {
case RawScript::kScriptTag:
return "script";
case RawScript::kLibraryTag:
return "library";
case RawScript::kSourceTag:
return "source";
case RawScript::kPatchTag:
return "patch";
default:
UNIMPLEMENTED();
}
UNREACHABLE();
return NULL;
}
void Script::set_url(const String& value) const {
StorePointer(&raw_ptr()->url_, value.raw());
}
@ -7042,6 +7060,18 @@ const char* Script::ToCString() const {
void Script::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
intptr_t id = ring->GetIdForObject(raw());
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
const String& name = String::Handle(url());
jsobj.AddProperty("name", name.ToCString());
jsobj.AddProperty("kind", GetKindAsCString());
if (ref) {
return;
}
const String& source = String::Handle(Source());
jsobj.AddProperty("source", source.ToCString());
}
@ -8159,6 +8189,15 @@ void Library::PrintToJSONStream(JSONStream* stream, bool ref) const {
}
}
}
{
JSONArray jsarr(&jsobj, "scripts");
Array& scripts = Array::Handle(LoadedScripts());
Script& script = Script::Handle();
for (intptr_t i = 0; i < scripts.Length(); i++) {
script ^= scripts.At(i);
jsarr.AddValue(script);
}
}
}

View file

@ -2361,6 +2361,7 @@ class Script : public Object {
RawScript::Kind kind() const {
return static_cast<RawScript::Kind>(raw_ptr()->kind_);
}
const char* GetKindAsCString() const;
intptr_t line_offset() const { return raw_ptr()->line_offset_; }
intptr_t col_offset() const { return raw_ptr()->col_offset_; }