Refactor VM service IDs:

- IDs are strings which can be concatenated together like paths.
- Isolate ID is now "/isolates/XXX"
- Function, field, class, library, and script IDs are now stable.
- Introduce <type-ref> tags.

R=turnidge@google.com

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@31358 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
johnmccutchan@google.com
2013-12-20 22:35:55 +00:00
parent 383468782e
commit 727d29d6b6
54 changed files with 39393 additions and 34058 deletions
@@ -29,7 +29,15 @@
</template>
</template>
</polymer-element><polymer-element name="error-view" extends="observatory-element">
</polymer-element><polymer-element name="service-ref" extends="observatory-element">
</polymer-element><polymer-element name="class-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element>
<polymer-element name="error-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
@@ -48,34 +56,42 @@
</div>
</template>
</polymer-element><polymer-element name="field-ref" extends="observatory-element">
</polymer-element><polymer-element name="field-ref" extends="service-ref">
<template>
<div>
<template if="{{ field['final'] }}"> final </template>
<template if="{{ field['const'] }}"> const </template>
<template if="{{ (field['declared_type']['name'] == 'dynamic' &amp;&amp; !field['final'] &amp;&amp; !field['const']) }}">
<template if="{{ ref['final'] }}"> final </template>
<template if="{{ ref['const'] }}"> const </template>
<template if="{{ (ref['declared_type']['name'] == 'dynamic' &amp;&amp; !ref['final'] &amp;&amp; !ref['const']) }}">
var
</template>
<template if="{{ (field['declared_type']['name'] != 'dynamic') }}">
<a href="{{ app.locationManager.currentIsolateClassLink(field['declared_type']['id']) }}">
{{ field['declared_type']['user_name'] }} </a>
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
<class-ref app="{{ app }}" ref="{{ ref['declared_type'] }}"></class-ref>
</template>
<a href="{{ app.locationManager.currentIsolateObjectLink(field['id'])}}">
{{ field['user_name'] }} </a>
<a href="{{ url }}">{{ name }}</a>
</div>
</template> </polymer-element><polymer-element name="instance-ref" extends="observatory-element">
</template> </polymer-element><polymer-element name="function-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="instance-ref" extends="service-ref">
<template>
<div>
<template if="{{ (instance['type'] == 'null') }}">
<template if="{{ (ref['type'] == 'null') }}">
{{ "null" }}
</template>
<template if="{{ (instance['type'] != 'null') }}">
<a href="{{ app.locationManager.currentIsolateObjectLink(instance['id'])}}">
{{ instance['preview'] }}
</a>
<template if="{{ (ref['type'] != 'null') }}">
<a href="{{ url }}">{{ name }} </a>
</template>
</div>
</template> </polymer-element><polymer-element name="class-view" extends="observatory-element">
</template>
</polymer-element><polymer-element name="library-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="class-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
@@ -84,13 +100,9 @@
class <strong>{{ cls['user_name'] }}</strong>
<template if="{{ cls['super']['type'] != 'Null' }}">
extends
<a href="{{ app.locationManager.currentIsolateClassLink(cls['super']['id'])}}">
{{ cls['super']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls['super'] }}"></class-ref>
</template>
<a class="pull-right" href="{{ app.locationManager.currentIsolateObjectLink(cls['library']['id'])}}">
{{ cls['library']['name'] }}
</a>
<library-ref app="{{ app }}" ref="{{ cls['library'] }}"></library-ref>
</div>
<div class="panel-body">
<table class="table table-hover">
@@ -120,8 +132,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ field in cls['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -135,8 +147,8 @@
</thead>
<tbody>
<tr template="" repeat="{{ function in cls['functions'] }}">
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['user_name'] }}</a></td>
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['name'] }}</a></td>
<td><function-ref app="{{ app }}" ref="{{ function }}"></function-ref></td>
<td><function-ref app="{{ app }}" ref="{{ function }}" internal=""></function-ref></td>
</tr>
</tbody>
</table>
@@ -150,6 +162,12 @@
</div>
</template>
</polymer-element>
<polymer-element name="code-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="disassembly-entry" extends="observatory-element">
<template>
<div class="row">
@@ -174,9 +192,7 @@
<div class="col-md-8 col-md-offset-2">
<div class="{{ cssPanelClass }}">
<div class="panel-heading">
<a href="{{ app.locationManager.currentIsolateObjectLink(code['function']['id'])}}">
{{ code['function']['user_name'] }} ({{ code['function']['name'] }})
</a>
<function-ref app="{{ app }}" ref="{{ code['function'] }}"></function-ref>
</div>
<div class="panel-body">
<div class="row">
@@ -215,10 +231,8 @@
<template if="{{ field['static'] }}">static</template>
<template if="{{ field['final'] }}">final</template>
<template if="{{ field['const'] }}">const</template>
{{ field['user_name'] }} ({{ field['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(field['class']['id'])}}">
{{ field['class']['user_name'] }}
</a>
{{ field['user_name'] }} ({{ field['name'] }})
<class-ref app="{{ app }}" ref="{{ field['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ field['guard_class'] == 'dynamic'}}">
@@ -227,9 +241,9 @@
assigned a single type, performance may improve.
</div>
</template>
<template if="{{ field['guard_class'] != 'dynamic'}}">
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp; (field['guard_class'] != 'unknown') }}">
<div class="alert alert-success">Field has monomorphic type</div>
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp;
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp;
field['guard_nullable'] }}">
<div class="alert alert-info">
Field has been assigned null. If a field is never assigned null,
@@ -237,9 +251,7 @@
</div>
</template>
<blockquote>
<a href="{{ app.locationManager.currentIsolateClassLink(field['guard_class']['id'])}}">
{{ field['guard_class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ field['guard_class'] }}"></class-ref>
</blockquote>
</template>
</div>
@@ -254,15 +266,13 @@
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel-heading">
{{ function['user_name'] }} ({{ function['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(function['class']['id'])}}">
{{ function['class']['name'] }}
</a>
{{ function['user_name'] }} ({{ function['name'] }})
<class-ref app="{{ app }}" ref="{{ function['class'] }}"></class-ref>
</div>
<div class="panel-body">
<div>
<a class="btn btn-primary" href="{{ app.locationManager.currentIsolateObjectLink(function['code']['id'])}}">Current Code</a>
<a class="btn btn-info" href="{{ app.locationManager.currentIsolateObjectLink(function['unoptimized_code']['id'])}}">Unoptimized Code</a>
<code-ref app="{{ app }}" ref="{{ function['code'] }}"></code-ref>
<code-ref app="{{ app }}" ref="{{ function['unoptimized_code'] }}"></code-ref>
</div>
<table class="table table-hover">
<tbody>
@@ -337,12 +347,10 @@
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel panel-warning">
<div class="panel-heading">
Instance of
<a href="{{ app.locationManager.currentIsolateClassLink(instance['class']['id'])}}">
{{ instance['class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ instance['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ instance['error'] == null }}">
@@ -357,8 +365,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ field in instance['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -372,7 +380,8 @@
</div>
</template>
</polymer-element><polymer-element name="json-view" extends="observatory-element">
</polymer-element>
<polymer-element name="json-view" extends="observatory-element">
<template>
<template bind="" if="{{ valueType == 'Primitive' }}">
<span>{{primitiveString}}</span>
@@ -401,6 +410,12 @@
</template>
</template>
</polymer-element>
<polymer-element name="script-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
@@ -412,7 +427,7 @@
{{ script['kind'] }}
</td>
<td>
<a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
<script-ref app="{{ app }}" ref="{{ script }}"></script-ref>
</td>
</tr>
</tbody>
@@ -422,9 +437,7 @@
<tbody>
<tr template="" repeat="{{ lib in library['libraries'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(lib['id'])}}">
{{ lib['url'] }}
</a>
<library-ref app="{{ app }}" ref="{{ lib }}"></library-ref>
</td>
</tr>
</tbody>
@@ -433,8 +446,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ variable in library['variables'] }}">
<td><field-ref app="{{ app }}" field="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ variable['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ variable['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -443,9 +456,7 @@
<tbody>
<tr template="" repeat="{{ func in library['functions'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(func['id'])}}">
{{ func['user_name'] }}
</a>
<function-ref app="{{ app }}" ref="{{ func }}"></function-ref>
</td>
</tr>
</tbody>
@@ -461,14 +472,10 @@
<tbody>
<tr template="" repeat="{{ cls in library['classes'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}"></class-ref>
</td>
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}" internal=""></class-ref>
</td>
</tr>
</tbody>
@@ -506,15 +513,15 @@
<tr>
<th>Depth</th>
<th>Function</th>
<th>Url</th>
<th>Script</th>
<th>Line</th>
</tr>
</thead>
<tbody>
<tr template="" repeat="{{ frame in trace['members'] }}">
<td>{{$index}}</td>
<td><a href="{{app.locationManager.currentIsolateObjectLink(frame['function']['id'])}}">{{ frame['name'] }}</a></td>
<td>{{ frame['url'] }}</td>
<td><function-ref app="{{ app }}" ref="{{ frame['function'] }}"></function-ref></td>
<td><script-ref app="{{ app }}" ref="{{ frame['script'] }}"></script-ref></td>
<td>{{ frame['line'] }}</td>
</tr>
</tbody>
@@ -588,7 +595,6 @@
<a class="navbar-brand" href="">Observatory</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<input class="span2 pull-right navbar-form" placeholder="VM Address" type="text" value="{{ app.requestManager.prefix }}">
</div>
</nav>
</template>
File diff suppressed because one or more lines are too long
@@ -29,7 +29,15 @@
</template>
</template>
</polymer-element><polymer-element name="error-view" extends="observatory-element">
</polymer-element><polymer-element name="service-ref" extends="observatory-element">
</polymer-element><polymer-element name="class-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element>
<polymer-element name="error-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
@@ -48,34 +56,42 @@
</div>
</template>
</polymer-element><polymer-element name="field-ref" extends="observatory-element">
</polymer-element><polymer-element name="field-ref" extends="service-ref">
<template>
<div>
<template if="{{ field['final'] }}"> final </template>
<template if="{{ field['const'] }}"> const </template>
<template if="{{ (field['declared_type']['name'] == 'dynamic' &amp;&amp; !field['final'] &amp;&amp; !field['const']) }}">
<template if="{{ ref['final'] }}"> final </template>
<template if="{{ ref['const'] }}"> const </template>
<template if="{{ (ref['declared_type']['name'] == 'dynamic' &amp;&amp; !ref['final'] &amp;&amp; !ref['const']) }}">
var
</template>
<template if="{{ (field['declared_type']['name'] != 'dynamic') }}">
<a href="{{ app.locationManager.currentIsolateClassLink(field['declared_type']['id']) }}">
{{ field['declared_type']['user_name'] }} </a>
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
<class-ref app="{{ app }}" ref="{{ ref['declared_type'] }}"></class-ref>
</template>
<a href="{{ app.locationManager.currentIsolateObjectLink(field['id'])}}">
{{ field['user_name'] }} </a>
<a href="{{ url }}">{{ name }}</a>
</div>
</template> </polymer-element><polymer-element name="instance-ref" extends="observatory-element">
</template> </polymer-element><polymer-element name="function-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="instance-ref" extends="service-ref">
<template>
<div>
<template if="{{ (instance['type'] == 'null') }}">
<template if="{{ (ref['type'] == 'null') }}">
{{ "null" }}
</template>
<template if="{{ (instance['type'] != 'null') }}">
<a href="{{ app.locationManager.currentIsolateObjectLink(instance['id'])}}">
{{ instance['preview'] }}
</a>
<template if="{{ (ref['type'] != 'null') }}">
<a href="{{ url }}">{{ name }} </a>
</template>
</div>
</template> </polymer-element><polymer-element name="class-view" extends="observatory-element">
</template>
</polymer-element><polymer-element name="library-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="class-view" extends="observatory-element">
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
@@ -84,13 +100,9 @@
class <strong>{{ cls['user_name'] }}</strong>
<template if="{{ cls['super']['type'] != 'Null' }}">
extends
<a href="{{ app.locationManager.currentIsolateClassLink(cls['super']['id'])}}">
{{ cls['super']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls['super'] }}"></class-ref>
</template>
<a class="pull-right" href="{{ app.locationManager.currentIsolateObjectLink(cls['library']['id'])}}">
{{ cls['library']['name'] }}
</a>
<library-ref app="{{ app }}" ref="{{ cls['library'] }}"></library-ref>
</div>
<div class="panel-body">
<table class="table table-hover">
@@ -120,8 +132,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ field in cls['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -135,8 +147,8 @@
</thead>
<tbody>
<tr template="" repeat="{{ function in cls['functions'] }}">
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['user_name'] }}</a></td>
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['name'] }}</a></td>
<td><function-ref app="{{ app }}" ref="{{ function }}"></function-ref></td>
<td><function-ref app="{{ app }}" ref="{{ function }}" internal=""></function-ref></td>
</tr>
</tbody>
</table>
@@ -150,6 +162,12 @@
</div>
</template>
</polymer-element>
<polymer-element name="code-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="disassembly-entry" extends="observatory-element">
<template>
<div class="row">
@@ -174,9 +192,7 @@
<div class="col-md-8 col-md-offset-2">
<div class="{{ cssPanelClass }}">
<div class="panel-heading">
<a href="{{ app.locationManager.currentIsolateObjectLink(code['function']['id'])}}">
{{ code['function']['user_name'] }} ({{ code['function']['name'] }})
</a>
<function-ref app="{{ app }}" ref="{{ code['function'] }}"></function-ref>
</div>
<div class="panel-body">
<div class="row">
@@ -215,10 +231,8 @@
<template if="{{ field['static'] }}">static</template>
<template if="{{ field['final'] }}">final</template>
<template if="{{ field['const'] }}">const</template>
{{ field['user_name'] }} ({{ field['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(field['class']['id'])}}">
{{ field['class']['user_name'] }}
</a>
{{ field['user_name'] }} ({{ field['name'] }})
<class-ref app="{{ app }}" ref="{{ field['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ field['guard_class'] == 'dynamic'}}">
@@ -227,9 +241,9 @@
assigned a single type, performance may improve.
</div>
</template>
<template if="{{ field['guard_class'] != 'dynamic'}}">
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp; (field['guard_class'] != 'unknown') }}">
<div class="alert alert-success">Field has monomorphic type</div>
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp;
<template if="{{ (field['guard_class'] != 'dynamic') &amp;&amp;
field['guard_nullable'] }}">
<div class="alert alert-info">
Field has been assigned null. If a field is never assigned null,
@@ -237,9 +251,7 @@
</div>
</template>
<blockquote>
<a href="{{ app.locationManager.currentIsolateClassLink(field['guard_class']['id'])}}">
{{ field['guard_class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ field['guard_class'] }}"></class-ref>
</blockquote>
</template>
</div>
@@ -254,15 +266,13 @@
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel-heading">
{{ function['user_name'] }} ({{ function['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(function['class']['id'])}}">
{{ function['class']['name'] }}
</a>
{{ function['user_name'] }} ({{ function['name'] }})
<class-ref app="{{ app }}" ref="{{ function['class'] }}"></class-ref>
</div>
<div class="panel-body">
<div>
<a class="btn btn-primary" href="{{ app.locationManager.currentIsolateObjectLink(function['code']['id'])}}">Current Code</a>
<a class="btn btn-info" href="{{ app.locationManager.currentIsolateObjectLink(function['unoptimized_code']['id'])}}">Unoptimized Code</a>
<code-ref app="{{ app }}" ref="{{ function['code'] }}"></code-ref>
<code-ref app="{{ app }}" ref="{{ function['unoptimized_code'] }}"></code-ref>
</div>
<table class="table table-hover">
<tbody>
@@ -337,12 +347,10 @@
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel panel-warning">
<div class="panel-heading">
Instance of
<a href="{{ app.locationManager.currentIsolateClassLink(instance['class']['id'])}}">
{{ instance['class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ instance['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ instance['error'] == null }}">
@@ -357,8 +365,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ field in instance['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -372,7 +380,8 @@
</div>
</template>
</polymer-element><polymer-element name="json-view" extends="observatory-element">
</polymer-element>
<polymer-element name="json-view" extends="observatory-element">
<template>
<template bind="" if="{{ valueType == 'Primitive' }}">
<span>{{primitiveString}}</span>
@@ -401,6 +410,12 @@
</template>
</template>
</polymer-element>
<polymer-element name="script-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
</polymer-element><polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
@@ -412,7 +427,7 @@
{{ script['kind'] }}
</td>
<td>
<a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
<script-ref app="{{ app }}" ref="{{ script }}"></script-ref>
</td>
</tr>
</tbody>
@@ -422,9 +437,7 @@
<tbody>
<tr template="" repeat="{{ lib in library['libraries'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(lib['id'])}}">
{{ lib['url'] }}
</a>
<library-ref app="{{ app }}" ref="{{ lib }}"></library-ref>
</td>
</tr>
</tbody>
@@ -433,8 +446,8 @@
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ variable in library['variables'] }}">
<td><field-ref app="{{ app }}" field="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ variable['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ variable['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -443,9 +456,7 @@
<tbody>
<tr template="" repeat="{{ func in library['functions'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(func['id'])}}">
{{ func['user_name'] }}
</a>
<function-ref app="{{ app }}" ref="{{ func }}"></function-ref>
</td>
</tr>
</tbody>
@@ -461,14 +472,10 @@
<tbody>
<tr template="" repeat="{{ cls in library['classes'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}"></class-ref>
</td>
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}" internal=""></class-ref>
</td>
</tr>
</tbody>
@@ -506,15 +513,15 @@
<tr>
<th>Depth</th>
<th>Function</th>
<th>Url</th>
<th>Script</th>
<th>Line</th>
</tr>
</thead>
<tbody>
<tr template="" repeat="{{ frame in trace['members'] }}">
<td>{{$index}}</td>
<td><a href="{{app.locationManager.currentIsolateObjectLink(frame['function']['id'])}}">{{ frame['name'] }}</a></td>
<td>{{ frame['url'] }}</td>
<td><function-ref app="{{ app }}" ref="{{ frame['function'] }}"></function-ref></td>
<td><script-ref app="{{ app }}" ref="{{ frame['script'] }}"></script-ref></td>
<td>{{ frame['line'] }}</td>
</tr>
</tbody>
@@ -588,7 +595,6 @@
<a class="navbar-brand" href="">Observatory</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<input class="span2 pull-right navbar-form" placeholder="VM Address" type="text" value="{{ app.requestManager.prefix }}">
</div>
</nav>
</template>
File diff suppressed because one or more lines are too long
@@ -2,24 +2,30 @@ library observatory_elements;
// Export elements.
export 'package:observatory/src/observatory_elements/breakpoint_list.dart';
export 'package:observatory/src/observatory_elements/class_ref.dart';
export 'package:observatory/src/observatory_elements/class_view.dart';
export 'package:observatory/src/observatory_elements/code_ref.dart';
export 'package:observatory/src/observatory_elements/code_view.dart';
export 'package:observatory/src/observatory_elements/collapsible_content.dart';
export 'package:observatory/src/observatory_elements/error_view.dart';
export 'package:observatory/src/observatory_elements/field_ref.dart';
export 'package:observatory/src/observatory_elements/field_view.dart';
export 'package:observatory/src/observatory_elements/function_ref.dart';
export 'package:observatory/src/observatory_elements/function_view.dart';
export 'package:observatory/src/observatory_elements/instance_ref.dart';
export 'package:observatory/src/observatory_elements/instance_view.dart';
export 'package:observatory/src/observatory_elements/isolate_list.dart';
export 'package:observatory/src/observatory_elements/isolate_summary.dart';
export 'package:observatory/src/observatory_elements/json_view.dart';
export 'package:observatory/src/observatory_elements/library_ref.dart';
export 'package:observatory/src/observatory_elements/library_view.dart';
export 'package:observatory/src/observatory_elements/message_viewer.dart';
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/script_ref.dart';
export 'package:observatory/src/observatory_elements/script_view.dart';
export 'package:observatory/src/observatory_elements/service_ref.dart';
export 'package:observatory/src/observatory_elements/source_view.dart';
export 'package:observatory/src/observatory_elements/stack_trace.dart';
@@ -2,18 +2,23 @@
<html>
<head>
<link rel="import" href="src/observatory_elements/breakpoint_list.html">
<link rel="import" href="src/observatory_elements/class_ref.html">
<link rel="import" href="src/observatory_elements/class_view.html">
<link rel="import" href="src/observatory_elements/code_ref.html">
<link rel="import" href="src/observatory_elements/code_view.html">
<link rel="import" href="src/observatory_elements/collapsible_content.html">
<link rel="import" href="src/observatory_elements/disassembly_entry.html">
<link rel="import" href="src/observatory_elements/error_view.html">
<link rel="import" href="src/observatory_elements/field_ref.html">
<link rel="import" href="src/observatory_elements/field_view.html">
<link rel="import" href="src/observatory_elements/function_ref.html">
<link rel="import" href="src/observatory_elements/function_view.html">
<link rel="import" href="src/observatory_elements/isolate_list.html">
<link rel="import" href="src/observatory_elements/isolate_summary.html">
<link rel="import" href="src/observatory_elements/instance_ref.html">
<link rel="import" href="src/observatory_elements/instance_view.html">
<link rel="import" href="src/observatory_elements/json_view.html">
<link rel="import" href="src/observatory_elements/library_ref.html">
<link rel="import" href="src/observatory_elements/library_view.html">
<link rel="import" href="src/observatory_elements/message_viewer.html">
<link rel="import" href="src/observatory_elements/navigation_bar.html">
@@ -22,6 +27,8 @@
<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/service_ref.html">
<link rel="import" href="src/observatory_elements/script_ref.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">
@@ -6,7 +6,7 @@ part of observatory;
/// State for a running isolate.
class Isolate extends Observable {
@observable int id;
@observable String id;
@observable String name;
@observable final Map<String, ScriptSource> scripts =
toObservable(new Map<String, ScriptSource>());
@@ -9,8 +9,8 @@ class IsolateManager extends Observable {
ObservatoryApplication _application;
ObservatoryApplication get application => _application;
@observable final Map<int, Isolate> isolates =
toObservable(new Map<int, Isolate>());
@observable final Map<String, Isolate> isolates =
toObservable(new Map<String, Isolate>());
static bool _foundIsolateInMembers(int id, List<Map> members) {
return members.any((E) => E['id'] == id);
@@ -24,7 +24,7 @@ class IsolateManager extends Observable {
});
}
Isolate getIsolate(int id) {
Isolate getIsolate(String id) {
Isolate isolate = isolates[id];
if (isolate == null) {
isolate = new Isolate(id, '');
@@ -10,7 +10,7 @@ part of observatory;
class LocationManager extends Observable {
static const int InvalidIsolateId = 0;
static const String defaultHash = '#/isolates/';
static final RegExp currentIsolateMatcher = new RegExp(r"#/isolates/\d+/");
static final RegExp currentIsolateMatcher = new RegExp(r"#/isolates/\d+");
ObservatoryApplication _application;
ObservatoryApplication get application => _application;
@@ -48,24 +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() {
String isolatePrefix = currentIsolateAnchorPrefix();
if (isolatePrefix == null) {
return InvalidIsolateId;
String currentIsolateId() {
var prefix = currentIsolateAnchorPrefix();
if (prefix == null) {
return '';
}
String id = isolatePrefix.split("/")[2];
return int.parse(id);
// Chop off the '/#'.
return prefix.substring(2);
}
/// If no anchor is set, set the default anchor and return true.
@@ -99,59 +90,16 @@ class LocationManager extends Observable {
return relativeLink(isolateId, l);
}
/// Create a request for [objectId] on the current isolate.
/// Create a request for [scriptURL] on the current isolate.
@observable
String currentIsolateObjectLink(int objectId) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return objectLink(isolateId, objectId);
}
/// Create a request for [cid] on the current isolate.
@observable
String currentIsolateClassLink(int cid) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
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);
String currentIsolateScriptLink(String scriptURL) {
var encoded = Uri.encodeComponent(scriptURL);
return currentIsolateRelativeLink('scripts/$encoded');
}
/// Create a request for [l] on [isolateId].
@observable
String relativeLink(int isolateId, String l) {
return '#/isolates/$isolateId/$l';
}
/// Create a request for [objectId] on [isolateId].
@observable
String objectLink(int isolateId, int objectId) {
return '#/isolates/$isolateId/objects/$objectId';
}
/// Create a request for [cid] on [isolateId].
@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';
String relativeLink(String isolateId, String l) {
return '#/$isolateId/$l';
}
}
@@ -19,7 +19,12 @@ abstract class RequestManager extends Observable {
/// Parse
void parseResponses(String responseString) {
var r = JSON.decode(responseString);
var r;
try {
r = JSON.decode(responseString);
} catch (e) {
setResponseError(e.message);
}
if (r is Map) {
setResponses([r]);
} else {
@@ -34,7 +39,7 @@ abstract class RequestManager extends Observable {
}
}
void setResponseError(HttpRequest request) {
void setResponseRequestError(HttpRequest request) {
String error = '${request.status} ${request.statusText}';
if (request.status == 0) {
error = 'No service found. Did you run with --enable-vm-service ?';
@@ -45,52 +50,20 @@ abstract class RequestManager extends Observable {
}]);
}
void setResponseError(String message) {
setResponses([{
'type': 'Error',
'text': message
}]);
}
/// Request [requestString] from the VM service. Updates [responses].
/// Will trigger [interceptor] if one is set.
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) {
if (e is FormatException) {
setResponseError(e.message);
} else {
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;
request(requestString).then((responseString) {
parseResponses(responseString);
}).catchError((e) {
setResponseError(e.target);
setResponseRequestError(e.target);
return null;
});
}
@@ -0,0 +1,13 @@
// 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_ref_element;
import 'package:polymer/polymer.dart';
import 'service_ref.dart';
@CustomTag('class-ref')
class ClassRefElement extends ServiceRefElement {
ClassRefElement.created() : super.created();
}
@@ -0,0 +1,9 @@
<head>
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="class-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
<script type="application/dart" src="class_ref.dart"></script>
</polymer-element>
@@ -2,7 +2,9 @@
<link rel="import" href="observatory_element.html">
<link rel="import" href="error_view.html">
<link rel="import" href="field_ref.html">
<link rel="import" href="function_ref.html">
<link rel="import" href="instance_ref.html">
<link rel="import" href="library_ref.html">
</head>
<polymer-element name="class-view" extends="observatory-element">
<template>
@@ -13,13 +15,9 @@
class <strong>{{ cls['user_name'] }}</strong>
<template if="{{ cls['super']['type'] != 'Null' }}">
extends
<a href="{{ app.locationManager.currentIsolateClassLink(cls['super']['id'])}}">
{{ cls['super']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls['super'] }}"></class-ref>
</template>
<a class="pull-right" href="{{ app.locationManager.currentIsolateObjectLink(cls['library']['id'])}}">
{{ cls['library']['name'] }}
</a>
<library-ref app="{{ app }}" ref="{{ cls['library'] }}"></library-ref>
</div>
<div class="panel-body">
<table class="table table-hover">
@@ -49,8 +47,8 @@
<table class="table table-hover">
<tbody>
<tr template repeat="{{ field in cls['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -64,8 +62,8 @@
</thead>
<tbody>
<tr template repeat="{{ function in cls['functions'] }}">
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['user_name'] }}</a></td>
<td><a href="{{ app.locationManager.currentIsolateObjectLink(function['id'])}}">{{ function['name'] }}</a></td>
<td><function-ref app="{{ app }}" ref="{{ function }}"></function-ref></td>
<td><function-ref app="{{ app }}" ref="{{ function }}" internal></function-ref></td>
</tr>
</tbody>
</table>
@@ -0,0 +1,13 @@
// 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 'package:polymer/polymer.dart';
import 'service_ref.dart';
@CustomTag('code-ref')
class CodeRefElement extends ServiceRefElement {
CodeRefElement.created() : super.created();
}
@@ -0,0 +1,9 @@
<head>
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="code-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
<script type="application/dart" src="code_ref.dart"></script>
</polymer-element>
@@ -1,5 +1,6 @@
<head>
<link rel="import" href="disassembly_entry.html">
<link rel="import" href="function_ref.html">
<link rel="import" href="observatory_element.html">
</head>
<polymer-element name="code-view" extends="observatory-element">
@@ -8,9 +9,7 @@
<div class="col-md-8 col-md-offset-2">
<div class="{{ cssPanelClass }}">
<div class="panel-heading">
<a href="{{ app.locationManager.currentIsolateObjectLink(code['function']['id'])}}">
{{ code['function']['user_name'] }} ({{ code['function']['name'] }})
</a>
<function-ref app="{{ app }}" ref="{{ code['function'] }}"></function-ref>
</div>
<div class="panel-body">
<div class="row">
@@ -5,10 +5,9 @@
library field_ref_element;
import 'package:polymer/polymer.dart';
import 'observatory_element.dart';
import 'service_ref.dart';
@CustomTag('field-ref')
class FieldRefElement extends ObservatoryElement {
@published Map field;
class FieldRefElement extends ServiceRefElement {
FieldRefElement.created() : super.created();
}
@@ -1,19 +1,19 @@
<head>
<link rel="import" href="class_ref.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="field-ref" extends="observatory-element">
<polymer-element name="field-ref" extends="service-ref">
<template>
<div>
<template if="{{ field['final'] }}"> final </template>
<template if="{{ field['const'] }}"> const </template>
<template if="{{ (field['declared_type']['name'] == 'dynamic' && !field['final'] && !field['const']) }}">
<template if="{{ ref['final'] }}"> final </template>
<template if="{{ ref['const'] }}"> const </template>
<template if="{{ (ref['declared_type']['name'] == 'dynamic' && !ref['final'] && !ref['const']) }}">
var
</template>
<template if="{{ (field['declared_type']['name'] != 'dynamic') }}">
<a href="{{ app.locationManager.currentIsolateClassLink(field['declared_type']['id']) }}">
{{ field['declared_type']['user_name'] }} </a>
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
<class-ref app="{{ app }}" ref="{{ ref['declared_type'] }}"></class-ref>
</template>
<a href="{{ app.locationManager.currentIsolateObjectLink(field['id'])}}">
{{ field['user_name'] }} </a>
<a href="{{ url }}">{{ name }}</a>
</div>
</template> <script type="application/dart" src="field_ref.dart"></script> </polymer-element>
@@ -1,4 +1,5 @@
<head>
<link rel="import" href="class_ref.html">
<link rel="import" href="observatory_element.html">
</head>
<polymer-element name="field-view" extends="observatory-element">
@@ -10,10 +11,8 @@
<template if="{{ field['static'] }}">static</template>
<template if="{{ field['final'] }}">final</template>
<template if="{{ field['const'] }}">const</template>
{{ field['user_name'] }} ({{ field['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(field['class']['id'])}}">
{{ field['class']['user_name'] }}
</a>
{{ field['user_name'] }} ({{ field['name'] }})
<class-ref app="{{ app }}" ref="{{ field['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ field['guard_class'] == 'dynamic'}}">
@@ -22,9 +21,9 @@
assigned a single type, performance may improve.
</div>
</template>
<template if="{{ field['guard_class'] != 'dynamic'}}">
<template if="{{ (field['guard_class'] != 'dynamic') && (field['guard_class'] != 'unknown') }}">
<div class="alert alert-success">Field has monomorphic type</div>
<template if="{{ (field['guard_class'] != 'dynamic') &&
<template if="{{ (field['guard_class'] != 'dynamic') &&
field['guard_nullable'] }}">
<div class="alert alert-info">
Field has been assigned null. If a field is never assigned null,
@@ -32,9 +31,7 @@
</div>
</template>
<blockquote>
<a href="{{ app.locationManager.currentIsolateClassLink(field['guard_class']['id'])}}">
{{ field['guard_class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ field['guard_class'] }}"></class-ref>
</blockquote>
</template>
</div>
@@ -0,0 +1,13 @@
// 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 'package:polymer/polymer.dart';
import 'service_ref.dart';
@CustomTag('function-ref')
class FunctionRefElement extends ServiceRefElement {
FunctionRefElement.created() : super.created();
}
@@ -0,0 +1,9 @@
<head>
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="function-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
<script type="application/dart" src="function_ref.dart"></script>
</polymer-element>
@@ -1,4 +1,6 @@
<head>
<link rel="import" href="class_ref.html">
<link rel="import" href="code_ref.html">
<link rel="import" href="observatory_element.html">
</head>
<polymer-element name="function-view" extends="observatory-element">
@@ -7,15 +9,13 @@
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel-heading">
{{ function['user_name'] }} ({{ function['name'] }})
<a class="pull-right" href="{{ app.locationManager.currentIsolateClassLink(function['class']['id'])}}">
{{ function['class']['name'] }}
</a>
{{ function['user_name'] }} ({{ function['name'] }})
<class-ref app="{{ app }}" ref="{{ function['class'] }}"></class-ref>
</div>
<div class="panel-body">
<div>
<a class="btn btn-primary" href="{{ app.locationManager.currentIsolateObjectLink(function['code']['id'])}}">Current Code</a>
<a class="btn btn-info" href="{{ app.locationManager.currentIsolateObjectLink(function['unoptimized_code']['id'])}}">Unoptimized Code</a>
<code-ref app="{{ app }}" ref="{{ function['code'] }}"></code-ref>
<code-ref app="{{ app }}" ref="{{ function['unoptimized_code'] }}"></code-ref>
</div>
<table class="table table-hover">
<tbody>
@@ -5,10 +5,16 @@
library instance_ref_element;
import 'package:polymer/polymer.dart';
import 'observatory_element.dart';
import 'service_ref.dart';
@CustomTag('instance-ref')
class InstanceRefElement extends ObservatoryElement {
@published Map instance;
class InstanceRefElement extends ServiceRefElement {
InstanceRefElement.created() : super.created();
String get name {
if (ref == null) {
return super.name;
}
return ref['preview'];
}
}
@@ -1,16 +1,17 @@
<head>
<link rel="import" href="observatory_element.html">
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="instance-ref" extends="observatory-element">
<polymer-element name="instance-ref" extends="service-ref">
<template>
<div>
<template if="{{ (instance['type'] == 'null') }}">
<template if="{{ (ref['type'] == 'null') }}">
{{ "null" }}
</template>
<template if="{{ (instance['type'] != 'null') }}">
<a href="{{ app.locationManager.currentIsolateObjectLink(instance['id'])}}">
{{ instance['preview'] }}
</a>
<template if="{{ (ref['type'] != 'null') }}">
<a href="{{ url }}">{{ name }} </a>
</template>
</div>
</template> <script type="application/dart" src="instance_ref.dart"></script> </polymer-element>
</template>
<script type="application/dart" src="instance_ref.dart"></script>
</polymer-element>
@@ -1,4 +1,5 @@
<head>
<link rel="import" href="class_ref.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="error_view.html">
<link rel="import" href="field_ref.html">
@@ -8,12 +9,10 @@
<template>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-warning">
<div class="panel panel-warning">
<div class="panel-heading">
Instance of
<a href="{{ app.locationManager.currentIsolateClassLink(instance['class']['id'])}}">
{{ instance['class']['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ instance['class'] }}"></class-ref>
</div>
<div class="panel-body">
<template if="{{ instance['error'] == null }}">
@@ -28,8 +27,8 @@
<table class="table table-hover">
<tbody>
<tr template repeat="{{ field in instance['fields'] }}">
<td><field-ref app="{{ app }}" field="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ field['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ field }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ field['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -44,4 +43,3 @@
</template>
<script type="application/dart" src="instance_view.dart"></script>
</polymer-element>
t>
@@ -9,7 +9,7 @@ import 'observatory_element.dart';
@CustomTag('isolate-summary')
class IsolateSummaryElement extends ObservatoryElement {
@published int isolate;
@published String isolate;
@published String name = '';
IsolateSummaryElement.created() : super.created();
@@ -0,0 +1,13 @@
// 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 'package:polymer/polymer.dart';
import 'service_ref.dart';
@CustomTag('library-ref')
class LibraryRefElement extends ServiceRefElement {
LibraryRefElement.created() : super.created();
}
@@ -0,0 +1,9 @@
<head>
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="library-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
<script type="application/dart" src="library_ref.dart"></script>
</polymer-element>
@@ -1,7 +1,11 @@
<head>
<link rel="import" href="observatory_element.html">
<link rel="import" href="class_ref.html">
<link rel="import" href="field_ref.html">
<link rel="import" href="function_ref.html">
<link rel="import" href="instance_ref.html">
<link rel="import" href="library_ref.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="script_ref.html">
</head>
<polymer-element name="library-view" extends="observatory-element">
<template>
@@ -14,7 +18,7 @@
{{ script['kind'] }}
</td>
<td>
<a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
<script-ref app="{{ app }}" ref="{{ script }}"></script-ref>
</td>
</tr>
</tbody>
@@ -24,9 +28,7 @@
<tbody>
<tr template repeat="{{ lib in library['libraries'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(lib['id'])}}">
{{ lib['url'] }}
</a>
<library-ref app="{{ app }}" ref="{{ lib }}"></library-ref>
</td>
</tr>
</tbody>
@@ -35,8 +37,8 @@
<table class="table table-hover">
<tbody>
<tr template repeat="{{ variable in library['variables'] }}">
<td><field-ref app="{{ app }}" field="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" instance="{{ variable['value'] }}"></instance-ref></td>
<td><field-ref app="{{ app }}" ref="{{ variable }}"></field-ref></td>
<td><instance-ref app="{{ app }}" ref="{{ variable['value'] }}"></instance-ref></td>
</tr>
</tbody>
</table>
@@ -45,9 +47,7 @@
<tbody>
<tr template repeat="{{ func in library['functions'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(func['id'])}}">
{{ func['user_name'] }}
</a>
<function-ref app="{{ app }}" ref="{{ func }}"></function-ref>
</td>
</tr>
</tbody>
@@ -63,14 +63,10 @@
<tbody>
<tr template repeat="{{ cls in library['classes'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['user_name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}"></class-ref>
</td>
<td>
<a href="{{ app.locationManager.currentIsolateClassLink(cls['id']) }}">
{{ cls['name'] }}
</a>
<class-ref app="{{ app }}" ref="{{ cls }}" internal></class-ref>
</td>
</tr>
</tbody>
@@ -8,10 +8,6 @@
<a class="navbar-brand" href="">Observatory</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<input class="span2 pull-right navbar-form"
placeholder="VM Address"
type="text"
value="{{ app.requestManager.prefix }}">
</div>
</nav>
</template>
@@ -22,6 +22,10 @@ class ObservatoryElement extends PolymerElement {
super.leftView();
}
void attributeChanged(String name, String oldValue, String newValue) {
super.attributeChanged(name, oldValue, newValue);
}
@published ObservatoryApplication app;
bool get applyAuthorStyles => true;
}
@@ -0,0 +1,13 @@
// 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_ref_element;
import 'package:polymer/polymer.dart';
import 'service_ref.dart';
@CustomTag('script-ref')
class ScriptRefElement extends ServiceRefElement {
ScriptRefElement.created() : super.created();
}
@@ -0,0 +1,10 @@
<head>
<link rel="import" href="observatory_element.html">
<link rel="import" href="service_ref.html">
</head>
<polymer-element name="script-ref" extends="service-ref">
<template>
<a href="{{ url }}">{{ name }}</a>
</template>
<script type="application/dart" src="script_ref.dart"></script>
</polymer-element>
@@ -0,0 +1,38 @@
// 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 service_ref_element;
import 'package:polymer/polymer.dart';
import 'observatory_element.dart';
@CustomTag('service-ref')
class ServiceRefElement extends ObservatoryElement {
@published Map ref;
@published bool internal = false;
ServiceRefElement.created() : super.created();
void refChanged(oldValue) {
notifyPropertyChange(#url, "", url);
notifyPropertyChange(#name, [], name);
}
String get url {
if ((app != null) && (ref != null)) {
return app.locationManager.currentIsolateRelativeLink(ref['id']);
}
return '';
}
String get name {
if (ref == null) {
return '';
}
String name_key = internal ? 'name' : 'user_name';
if (ref[name_key] != null) {
return ref[name_key];
}
return '';
}
}
@@ -0,0 +1,6 @@
<head>
<link rel="import" href="observatory_element.html">
</head>
<polymer-element name="service-ref" extends="observatory-element">
<script type="application/dart" src="service_ref.dart"></script>
</polymer-element>
@@ -1,5 +1,7 @@
<head>
<link rel="import" href="function_ref.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="script_ref.html">
</head>
<polymer-element name="stack-trace" extends="observatory-element">
<template>
@@ -9,15 +11,15 @@
<tr>
<th>Depth</th>
<th>Function</th>
<th>Url</th>
<th>Script</th>
<th>Line</th>
</tr>
</thead>
<tbody>
<tr template repeat="{{ frame in trace['members'] }}">
<td>{{$index}}</td>
<td><a href="{{app.locationManager.currentIsolateObjectLink(frame['function']['id'])}}">{{ frame['name'] }}</a></td>
<td>{{ frame['url'] }}</td>
<td><function-ref app="{{ app }}" ref="{{ frame['function'] }}"></function-ref></td>
<td><script-ref app="{{ app }}" ref="{{ frame['script'] }}"></script-ref></td>
<td>{{ frame['line'] }}</td>
</tr>
</tbody>
+3 -2
View File
@@ -29,8 +29,9 @@ class RunningIsolates implements MessageRouter {
var result = {};
isolates.forEach((portId, runningIsolate) {
members.add({
'id': portId,
'name': runningIsolate.name
'type': 'Isolate',
'id': 'isolates/$portId',
'name': runningIsolate.name,
});
});
result['type'] = 'IsolateList';
+250 -21
View File
@@ -1808,6 +1808,32 @@ void Class::AddFunction(const Function& function) const {
}
intptr_t Class::FindFunctionIndex(const Function& needle) const {
Isolate* isolate = Isolate::Current();
if (EnsureIsFinalized(isolate) != Error::null()) {
return -1;
}
ReusableHandleScope reused_handles(isolate);
Array& funcs = reused_handles.ArrayHandle();
funcs ^= functions();
ASSERT(!funcs.IsNull());
Function& function = reused_handles.FunctionHandle();
String& function_name = reused_handles.StringHandle();
String& needle_name = String::Handle(isolate);
needle_name ^= needle.name();
const intptr_t len = funcs.Length();
for (intptr_t i = 0; i < len; i++) {
function ^= funcs.At(i);
function_name ^= function.name();
if (function_name.Equals(needle_name)) {
return i;
}
}
// No function found.
return -1;
}
void Class::AddClosureFunction(const Function& function) const {
GrowableObjectArray& closures =
GrowableObjectArray::Handle(raw_ptr()->closure_functions_);
@@ -1848,6 +1874,31 @@ RawFunction* Class::LookupClosureFunction(intptr_t token_pos) const {
return closure.raw();
}
intptr_t Class::FindClosureIndex(intptr_t token_pos) const {
if (raw_ptr()->closure_functions_ == GrowableObjectArray::null()) {
return -1;
}
Isolate* isolate = Isolate::Current();
ReusableHandleScope reused_handles(isolate);
const GrowableObjectArray& closures =
GrowableObjectArray::Handle(isolate, raw_ptr()->closure_functions_);
Function& closure = reused_handles.FunctionHandle();
intptr_t num_closures = closures.Length();
intptr_t best_fit_token_pos = -1;
intptr_t best_fit_index = -1;
for (intptr_t i = 0; i < num_closures; i++) {
closure ^= closures.At(i);
ASSERT(!closure.IsNull());
if ((closure.token_pos() <= token_pos) &&
(token_pos <= closure.end_token_pos()) &&
(best_fit_token_pos < closure.token_pos())) {
best_fit_index = i;
best_fit_token_pos = closure.token_pos();
}
}
return best_fit_index;
}
void Class::set_signature_function(const Function& value) const {
ASSERT(value.IsClosureFunction() || value.IsSignatureFunction());
@@ -2400,6 +2451,32 @@ void Class::SetFields(const Array& value) const {
}
intptr_t Class::FindFieldIndex(const Field& needle) const {
Isolate* isolate = Isolate::Current();
if (EnsureIsFinalized(isolate) != Error::null()) {
return -1;
}
ReusableHandleScope reused_handles(isolate);
Array& fields_array = reused_handles.ArrayHandle();
fields_array ^= fields();
ASSERT(!fields_array.IsNull());
Field& field = reused_handles.FieldHandle();
String& field_name = reused_handles.StringHandle();
String& needle_name = String::Handle(isolate);
needle_name ^= needle.name();
const intptr_t len = fields_array.Length();
for (intptr_t i = 0; i < len; i++) {
field ^= fields_array.At(i);
field_name ^= field.name();
if (field_name.Equals(needle_name)) {
return i;
}
}
// No field found found.
return -1;
}
template <class FakeInstance>
RawClass* Class::New(intptr_t index) {
ASSERT(Object::class_class() != Class::null());
@@ -3249,7 +3326,7 @@ void Class::PrintToJSONStream(JSONStream* stream, bool ref) const {
const char* user_visible_class_name =
String::Handle(UserVisibleName()).ToCString();
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id());
jsobj.AddPropertyF("id", "classes/%" Pd "", id());
jsobj.AddProperty("name", internal_class_name);
jsobj.AddProperty("user_name", user_visible_class_name);
if (!ref) {
@@ -5633,11 +5710,26 @@ void Function::PrintToJSONStream(JSONStream* stream, bool ref) const {
const char* internal_function_name = String::Handle(name()).ToCString();
const char* function_name =
String::Handle(QualifiedUserVisibleName()).ToCString();
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
intptr_t id = ring->GetIdForObject(raw());
Class& cls = Class::Handle(Owner());
Error& err = Error::Handle();
err ^= cls.EnsureIsFinalized(Isolate::Current());
ASSERT(err.IsNull());
const Function& func = *this;
intptr_t id;
if (IsNonImplicitClosureFunction()) {
id = cls.FindClosureIndex(token_pos());
} else {
id = cls.FindFunctionIndex(func);
}
ASSERT(id >= 0);
intptr_t cid = cls.id();
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
if (IsNonImplicitClosureFunction()) {
jsobj.AddPropertyF("id", "classes/%" Pd "/closures/%" Pd "", cid, id);
} else {
jsobj.AddPropertyF("id", "classes/%" Pd "/functions/%" Pd "", cid, id);
}
jsobj.AddProperty("name", internal_function_name);
jsobj.AddProperty("user_name", function_name);
if (ref) return;
@@ -5966,10 +6058,12 @@ void Field::PrintToJSONStreamWithInstance(JSONStream* stream,
JSONObject jsobj(stream);
const char* internal_field_name = String::Handle(name()).ToCString();
const char* field_name = String::Handle(UserVisibleName()).ToCString();
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
intptr_t id = ring->GetIdForObject(raw());
Class& cls = Class::Handle(owner());
intptr_t id = cls.FindFieldIndex(*this);
ASSERT(id >= 0);
intptr_t cid = cls.id();
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
jsobj.AddPropertyF("id", "classes/%" Pd "/fields/%" Pd "", cid, id);
jsobj.AddProperty("name", internal_field_name);
jsobj.AddProperty("user_name", field_name);
if (is_static()) {
@@ -5979,7 +6073,7 @@ void Field::PrintToJSONStreamWithInstance(JSONStream* stream,
const Object& valueObj = Object::Handle(instance.GetField(*this));
jsobj.AddProperty("value", valueObj);
}
Class& cls = Class::Handle(owner());
jsobj.AddProperty("owner", cls);
AbstractType& declared_type = AbstractType::Handle(type());
cls = declared_type.type_class();
@@ -7133,12 +7227,14 @@ 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());
ASSERT(!name.IsNull());
const String& encoded_url = String::Handle(String::EncodeURI(name));
ASSERT(!encoded_url.IsNull());
jsobj.AddPropertyF("id", "scripts/%s", encoded_url.ToCString());
jsobj.AddProperty("name", name.ToCString());
jsobj.AddProperty("user_name", name.ToCString());
jsobj.AddProperty("kind", GetKindAsCString());
if (ref) {
return;
@@ -8207,13 +8303,13 @@ const char* Library::ToCString() const {
void Library::PrintToJSONStream(JSONStream* stream, bool ref) const {
const char* library_name = String::Handle(name()).ToCString();
const char* library_url = String::Handle(url()).ToCString();
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
intptr_t id = ring->GetIdForObject(raw());
intptr_t id = index();
ASSERT(id >= 0);
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
jsobj.AddPropertyF("id", "libraries/%" Pd "", id);
jsobj.AddProperty("name", library_name);
jsobj.AddProperty("url", library_url);
jsobj.AddProperty("user_name", library_url);
if (ref) return;
{
JSONArray jsarr(&jsobj, "classes");
@@ -9780,16 +9876,27 @@ const char* Code::ToCString() const {
void Code::PrintToJSONStream(JSONStream* stream, bool ref) const {
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
Isolate* isolate = Isolate::Current();
ObjectIdRing* ring = isolate->object_id_ring();
intptr_t id = ring->GetIdForObject(raw());
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
Function& func = Function::Handle();
String& name = String::Handle();
func ^= function();
ASSERT(!func.IsNull());
name ^= func.name();
const char* internal_function_name = name.ToCString();
jsobj.AddPropertyF("name", "%s%s", is_optimized() ? "*" : "",
internal_function_name);
name ^= func.QualifiedUserVisibleName();
const char* function_name = name.ToCString();
jsobj.AddPropertyF("user_name", "%s%s", is_optimized() ? "*" : "",
function_name);
if (ref) {
jsobj.AddProperty("type", "@Code");
jsobj.AddProperty("id", id);
return;
}
jsobj.AddProperty("type", "Code");
jsobj.AddProperty("id", id);
jsobj.AddProperty("is_optimized", is_optimized());
jsobj.AddProperty("is_alive", is_alive());
jsobj.AddProperty("function", Object::Handle(function()));
@@ -11491,7 +11598,7 @@ void Instance::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
Class& cls = Class::Handle(this->clazz());
jsobj.AddProperty("class", cls);
@@ -14350,6 +14457,128 @@ RawString* String::EscapeSpecialCharacters(const String& str) {
}
static bool IsPercent(int32_t c) {
return c == '%';
}
static bool IsURISafeCharacter(int32_t c) {
if ((c >= '0') && (c <= '9')) {
return true;
}
if ((c >= 'a') && (c <= 'z')) {
return true;
}
if ((c >= 'A') && (c <= 'Z')) {
return true;
}
return (c == '-') || (c == '_') || (c == '.') || (c == '~');
}
static int32_t GetHexCharacter(int32_t c) {
ASSERT(c >= 0);
ASSERT(c < 16);
const char* hex = "0123456789ABCDEF";
return hex[c];
}
static int32_t GetHexValue(int32_t c) {
if (c >= '0' && c <= '9') {
return c - '0';
}
if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
UNREACHABLE();
return 0;
}
static int32_t MergeHexCharacters(int32_t c1, int32_t c2) {
return GetHexValue(c1) << 4 | GetHexValue(c2);
}
RawString* String::EncodeURI(const String& str) {
// URI encoding is only specified for one byte strings.
ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
intptr_t num_escapes = 0;
intptr_t len = str.Length();
{
CodePointIterator cpi(str);
while (cpi.Next()) {
int32_t code_point = cpi.Current();
if (!IsURISafeCharacter(code_point)) {
num_escapes += 2;
}
}
}
const String& dststr = String::Handle(
OneByteString::New(len + num_escapes, Heap::kNew));
{
intptr_t index = 0;
CodePointIterator cpi(str);
while (cpi.Next()) {
int32_t code_point = cpi.Current();
if (!IsURISafeCharacter(code_point)) {
OneByteString::SetCharAt(dststr, index, '%');
OneByteString::SetCharAt(dststr, index + 1,
GetHexCharacter(code_point >> 4));
OneByteString::SetCharAt(dststr, index + 2,
GetHexCharacter(code_point & 0xF));
index += 3;
} else {
OneByteString::SetCharAt(dststr, index, code_point);
index += 1;
}
}
}
return dststr.raw();
}
RawString* String::DecodeURI(const String& str) {
// URI encoding is only specified for one byte strings.
ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
CodePointIterator cpi(str);
intptr_t num_escapes = 0;
intptr_t len = str.Length();
{
CodePointIterator cpi(str);
while (cpi.Next()) {
int32_t code_point = cpi.Current();
if (IsPercent(code_point)) {
num_escapes += 2;
}
}
}
ASSERT(len - num_escapes > 0);
const String& dststr = String::Handle(
OneByteString::New(len - num_escapes, Heap::kNew));
{
intptr_t index = 0;
CodePointIterator cpi(str);
while (cpi.Next()) {
int32_t code_point = cpi.Current();
if (IsPercent(code_point)) {
ASSERT(cpi.Next());
int32_t ch1 = cpi.Current();
cpi.Next();
int32_t ch2 = cpi.Current();
int32_t merged = MergeHexCharacters(ch1, ch2);
OneByteString::SetCharAt(dststr, index, merged);
} else {
OneByteString::SetCharAt(dststr, index, code_point);
}
index++;
}
}
return dststr.raw();
}
RawString* String::NewFormatted(const char* format, ...) {
va_list args;
va_start(args, format);
+7 -2
View File
@@ -878,6 +878,7 @@ class Class : public Object {
RawArray* fields() const { return raw_ptr()->fields_; }
void SetFields(const Array& value) const;
intptr_t FindFieldIndex(const Field& field) const;
// Returns an array of all fields of this class and its superclasses indexed
// by offset in words.
@@ -889,12 +890,14 @@ class Class : public Object {
RawArray* functions() const { return raw_ptr()->functions_; }
void SetFunctions(const Array& value) const;
void AddFunction(const Function& function) const;
intptr_t FindFunctionIndex(const Function& function) const;
RawGrowableObjectArray* closures() const {
return raw_ptr()->closure_functions_;
}
void AddClosureFunction(const Function& function) const;
RawFunction* LookupClosureFunction(intptr_t token_pos) const;
intptr_t FindClosureIndex(intptr_t token_pos) const;
RawFunction* LookupDynamicFunction(const String& name) const;
RawFunction* LookupDynamicFunctionAllowPrivate(const String& name) const;
@@ -5072,7 +5075,8 @@ class String : public Instance {
intptr_t len);
static RawString* EscapeSpecialCharacters(const String& str);
static RawString* EncodeURI(const String& str);
static RawString* DecodeURI(const String& str);
static RawString* Concat(const String& str1,
const String& str2,
Heap::Space space = Heap::kNew);
@@ -5163,7 +5167,6 @@ class OneByteString : public AllStatic {
*CharAddr(str, index) = code_point;
}
static RawOneByteString* EscapeSpecialCharacters(const String& str);
// We use the same maximum elements for all strings.
static const intptr_t kBytesPerElement = 1;
static const intptr_t kMaxElements = String::kMaxElements;
@@ -5387,6 +5390,8 @@ class ExternalOneByteString : public AllStatic {
}
static RawOneByteString* EscapeSpecialCharacters(const String& str);
static RawOneByteString* EncodeURI(const String& str);
static RawOneByteString* DecodeURI(const String& str);
static const ClassId kClassId = kExternalOneByteStringCid;
+162
View File
@@ -332,6 +332,32 @@ TEST_CASE(StringCompareTo) {
}
TEST_CASE(StringEncodeURI) {
const char* kInput =
"file:///usr/local/johnmccutchan/workspace/dart-repo/dart/test.dart";
const char* kOutput =
"file%3A%2F%2F%2Fusr%2Flocal%2Fjohnmccutchan%2Fworkspace%2F"
"dart-repo%2Fdart%2Ftest.dart";
const String& input = String::Handle(String::New(kInput));
const String& output = String::Handle(String::New(kOutput));
const String& encoded = String::Handle(String::EncodeURI(input));
EXPECT(output.Equals(encoded));
}
TEST_CASE(StringDecodeURI) {
const char* kOutput =
"file:///usr/local/johnmccutchan/workspace/dart-repo/dart/test.dart";
const char* kInput =
"file%3A%2F%2F%2Fusr%2Flocal%2Fjohnmccutchan%2Fworkspace%2F"
"dart-repo%2Fdart%2Ftest.dart";
const String& input = String::Handle(String::New(kInput));
const String& output = String::Handle(String::New(kOutput));
const String& decoded = String::Handle(String::DecodeURI(input));
EXPECT(output.Equals(decoded));
}
TEST_CASE(Mint) {
// On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
// be allocated if it does fit into a Smi.
@@ -2749,6 +2775,8 @@ TEST_CASE(FieldTests) {
}
// Expose helper function from object.cc for testing.
bool EqualsIgnoringPrivate(const String& name, const String& private_name);
@@ -3391,6 +3419,140 @@ static RawClass* GetClass(const Library& lib, const char* name) {
}
TEST_CASE(FindFieldIndex) {
const char* kScriptChars =
"class A {\n"
" var a;\n"
" var b;\n"
"}\n"
"class B {\n"
" var d;\n"
"}\n"
"test() {\n"
" new A();\n"
" new B();\n"
"}";
Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(h_lib);
Dart_Handle result = Dart_Invoke(h_lib, NewString("test"), 0, NULL);
EXPECT_VALID(result);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
const Class& class_a = Class::Handle(GetClass(lib, "A"));
const Array& class_a_fields = Array::Handle(class_a.fields());
const Class& class_b = Class::Handle(GetClass(lib, "B"));
const Field& field_a = Field::Handle(GetField(class_a, "a"));
const Field& field_b = Field::Handle(GetField(class_a, "b"));
const Field& field_d = Field::Handle(GetField(class_b, "d"));
intptr_t field_a_index = class_a.FindFieldIndex(field_a);
intptr_t field_b_index = class_a.FindFieldIndex(field_b);
intptr_t field_d_index = class_a.FindFieldIndex(field_d);
// Valid index.
EXPECT_GE(field_a_index, 0);
// Valid index.
EXPECT_GE(field_b_index, 0);
// Invalid index.
EXPECT_EQ(field_d_index, -1);
Field& field_a_from_index = Field::Handle();
field_a_from_index ^= class_a_fields.At(field_a_index);
ASSERT(!field_a_from_index.IsNull());
// Same field.
EXPECT_EQ(field_a.raw(), field_a_from_index.raw());
Field& field_b_from_index = Field::Handle();
field_b_from_index ^= class_a_fields.At(field_b_index);
ASSERT(!field_b_from_index.IsNull());
// Same field.
EXPECT_EQ(field_b.raw(), field_b_from_index.raw());
}
TEST_CASE(FindFunctionIndex) {
const char* kScriptChars =
"class A {\n"
" void a() {}\n"
" void b() {}\n"
"}\n"
"class B {\n"
" dynamic d() {}\n"
"}\n"
"test() {\n"
" new A();\n"
" new B();\n"
"}";
Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(h_lib);
Dart_Handle result = Dart_Invoke(h_lib, NewString("test"), 0, NULL);
EXPECT_VALID(result);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
const Class& class_a = Class::Handle(GetClass(lib, "A"));
const Array& class_a_funcs = Array::Handle(class_a.functions());
const Class& class_b = Class::Handle(GetClass(lib, "B"));
const Function& func_a = Function::Handle(GetFunction(class_a, "a"));
const Function& func_b = Function::Handle(GetFunction(class_a, "b"));
const Function& func_d = Function::Handle(GetFunction(class_b, "d"));
intptr_t func_a_index = class_a.FindFunctionIndex(func_a);
intptr_t func_b_index = class_a.FindFunctionIndex(func_b);
intptr_t func_d_index = class_a.FindFunctionIndex(func_d);
// Valid index.
EXPECT_GE(func_a_index, 0);
// Valid index.
EXPECT_GE(func_b_index, 0);
// Invalid index.
EXPECT_EQ(func_d_index, -1);
Function& func_a_from_index = Function::Handle();
func_a_from_index ^= class_a_funcs.At(func_a_index);
ASSERT(!func_a_from_index.IsNull());
// Same function.
EXPECT_EQ(func_a.raw(), func_a_from_index.raw());
Function& func_b_from_index = Function::Handle();
func_b_from_index ^= class_a_funcs.At(func_b_index);
ASSERT(!func_b_from_index.IsNull());
// Same function.
EXPECT_EQ(func_b.raw(), func_b_from_index.raw());
}
TEST_CASE(FindClosureIndex) {
// Allocate the class first.
const String& class_name = String::Handle(Symbols::New("MyClass"));
const Script& script = Script::Handle();
const Class& cls = Class::Handle(CreateDummyClass(class_name, script));
const Array& functions = Array::Handle(Array::New(1));
Function& parent = Function::Handle();
const String& parent_name = String::Handle(Symbols::New("foo_papa"));
parent = Function::New(parent_name, RawFunction::kRegularFunction,
false, false, false, false, false, cls, 0);
functions.SetAt(0, parent);
cls.SetFunctions(functions);
Function& function = Function::Handle();
const String& function_name = String::Handle(Symbols::New("foo"));
function = Function::NewClosureFunction(function_name, parent, 0);
// Add closure function to class.
cls.AddClosureFunction(function);
// Token position 0 should return a valid index.
intptr_t good_closure_index = cls.FindClosureIndex(0);
EXPECT_GE(good_closure_index, 0);
// Token position 1 should return an invalid index.
intptr_t bad_closure_index = cls.FindClosureIndex(1);
EXPECT_EQ(bad_closure_index, -1);
// Retrieve closure function via index.
const GrowableObjectArray& closures = GrowableObjectArray::Handle(
cls.closures());
Function& func_from_index = Function::Handle();
func_from_index ^= closures.At(good_closure_index);
// Same closure function.
EXPECT_EQ(func_from_index.raw(), function.raw());
}
static void PrintMetadata(const char* name, const Object& data) {
if (data.IsError()) {
OS::Print("Error in metadata evaluation for %s: '%s'\n",
+215 -11
View File
@@ -196,15 +196,15 @@ static void HandleStackTrace(Isolate* isolate, JSONStream* js) {
jsobj.AddProperty("type", "StackTrace");
JSONArray jsarr(&jsobj, "members");
intptr_t n_frames = stack->Length();
String& url = String::Handle();
String& function = String::Handle();
Script& script = Script::Handle();
for (int i = 0; i < n_frames; i++) {
ActivationFrame* frame = stack->FrameAt(i);
url ^= frame->SourceUrl();
script ^= frame->SourceScript();
function ^= frame->function().UserVisibleName();
JSONObject jsobj(&jsarr);
jsobj.AddProperty("name", function.ToCString());
jsobj.AddProperty("url", url.ToCString());
jsobj.AddProperty("script", script);
jsobj.AddProperty("line", frame->LineNumber());
jsobj.AddProperty("function", frame->function());
jsobj.AddProperty("code", frame->code());
@@ -239,6 +239,93 @@ static void HandleEcho(Isolate* isolate, JSONStream* js) {
}
#define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
if (!GetIntegerId(arg, &id)) { \
PrintError(js, "Must specify collection object id: %s/id", collection); \
return; \
} \
if ((id < 0) || (id >= length)) { \
PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \
length); \
return; \
}
static bool GetIntegerId(const char* s, intptr_t* id) {
if ((s == NULL) || (*s == '\0')) {
// Empty string.
return false;
}
if (id == NULL) {
// No id pointer.
return false;
}
intptr_t r = 0;
char* end_ptr = NULL;
r = strtol(s, &end_ptr, 10);
if (end_ptr == s) {
// String was not advanced at all, cannot be valid.
return false;
}
*id = r;
return true;
}
static void HandleClassesClosures(Isolate* isolate, const Class& cls,
JSONStream* js) {
const GrowableObjectArray& closures =
GrowableObjectArray::Handle(cls.closures());
intptr_t id;
if (js->num_arguments() > 4) {
PrintError(js, "Command too long");
return;
}
CHECK_COLLECTION_ID_BOUNDS("closures", closures.Length(), js->GetArgument(3),
id, js);
Function& function = Function::Handle();
function ^= closures.At(id);
ASSERT(!function.IsNull());
function.PrintToJSONStream(js, false);
}
static void HandleClassesFunctions(Isolate* isolate, const Class& cls,
JSONStream* js) {
const Array& functions =
Array::Handle(cls.functions());
intptr_t id;
if (js->num_arguments() > 4) {
PrintError(js, "Command too long");
return;
}
CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(),
js->GetArgument(3), id, js);
Function& function = Function::Handle();
function ^= functions.At(id);
ASSERT(!function.IsNull());
function.PrintToJSONStream(js, false);
}
static void HandleClassesFields(Isolate* isolate, const Class& cls,
JSONStream* js) {
const Array& fields =
Array::Handle(cls.fields());
intptr_t id;
if (js->num_arguments() > 4) {
PrintError(js, "Command too long");
return;
}
CHECK_COLLECTION_ID_BOUNDS("fields", fields.Length(), js->GetArgument(3),
id, js);
Field& field = Field::Handle();
field ^= fields.At(id);
ASSERT(!field.IsNull());
field.PrintToJSONStream(js, false);
}
static void HandleClasses(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
ClassTable* table = isolate->class_table();
@@ -246,14 +333,34 @@ static void HandleClasses(Isolate* isolate, JSONStream* js) {
return;
}
ASSERT(js->num_arguments() >= 2);
intptr_t id = atoi(js->GetArgument(1));
intptr_t id;
if (!GetIntegerId(js->GetArgument(1), &id)) {
PrintError(js, "Must specify collection object id: /classes/id");
return;
}
ClassTable* table = isolate->class_table();
if (!table->IsValidIndex(id)) {
Object::null_object().PrintToJSONStream(js, false);
} else {
Class& cls = Class::Handle(table->At(id));
cls.PrintToJSONStream(js, false);
PrintError(js, "%" Pd " is not a valid class id.", id);;
return;
}
Class& cls = Class::Handle(table->At(id));
if (js->num_arguments() == 2) {
cls.PrintToJSONStream(js, false);
return;
} else if (js->num_arguments() >= 3) {
const char* second = js->GetArgument(2);
if (!strcmp(second, "closures")) {
HandleClassesClosures(isolate, cls, js);
} else if (!strcmp(second, "fields")) {
HandleClassesFields(isolate, cls, js);
} else if (!strcmp(second, "functions")) {
HandleClassesFunctions(isolate, cls, js);
} else {
PrintError(js, "Invalid sub collection %s", second);
}
return;
}
UNREACHABLE();
}
@@ -268,17 +375,109 @@ static void HandleLibrary(Isolate* isolate, JSONStream* js) {
}
static void HandleLibraries(Isolate* isolate, JSONStream* js) {
// TODO(johnmccutchan): Support fields and functions on libraries.
REQUIRE_COLLECTION_ID("libraries");
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate->object_store()->libraries());
ASSERT(!libs.IsNull());
intptr_t id = 0;
CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
id, js);
Library& lib = Library::Handle();
lib ^= libs.At(id);
ASSERT(!lib.IsNull());
lib.PrintToJSONStream(js, false);
}
static void HandleObjects(Isolate* isolate, JSONStream* js) {
REQUIRE_COLLECTION_ID("objects");
ASSERT(js->num_arguments() >= 2);
ObjectIdRing* ring = isolate->object_id_ring();
ASSERT(ring != NULL);
intptr_t id = atoi(js->GetArgument(1));
intptr_t id = -1;
if (!GetIntegerId(js->GetArgument(1), &id)) {
Object::null_object().PrintToJSONStream(js, false);
return;
}
Object& obj = Object::Handle(ring->GetObjectForId(id));
obj.PrintToJSONStream(js, false);
}
static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "ScriptList");
{
JSONArray members(&jsobj, "members");
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate->object_store()->libraries());
int num_libs = libs.Length();
Library &lib = Library::Handle();
Script& script = Script::Handle();
for (intptr_t i = 0; i < num_libs; i++) {
lib ^= libs.At(i);
ASSERT(!lib.IsNull());
ASSERT(Smi::IsValid(lib.index()));
const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
ASSERT(!loaded_scripts.IsNull());
intptr_t num_scripts = loaded_scripts.Length();
for (intptr_t i = 0; i < num_scripts; i++) {
script ^= loaded_scripts.At(i);
members.AddValue(script);
}
}
}
}
static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate->object_store()->libraries());
int num_libs = libs.Length();
Library &lib = Library::Handle();
Script& script = Script::Handle();
String& url = String::Handle();
const String& id = String::Handle(String::New(js->GetArgument(1)));
ASSERT(!id.IsNull());
// The id is the url of the script % encoded, decode it.
String& requested_url = String::Handle(String::DecodeURI(id));
for (intptr_t i = 0; i < num_libs; i++) {
lib ^= libs.At(i);
ASSERT(!lib.IsNull());
ASSERT(Smi::IsValid(lib.index()));
const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
ASSERT(!loaded_scripts.IsNull());
intptr_t num_scripts = loaded_scripts.Length();
for (intptr_t i = 0; i < num_scripts; i++) {
script ^= loaded_scripts.At(i);
ASSERT(!script.IsNull());
url ^= script.url();
if (url.Equals(requested_url)) {
script.PrintToJSONStream(js, false);
return;
}
}
}
PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
}
static void HandleScripts(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
// Enumerate all scripts.
HandleScriptsEnumerate(isolate, js);
} else if (js->num_arguments() == 2) {
// Fetch specific script.
HandleScriptsFetch(isolate, js);
} else {
PrintError(js, "Command too long");
}
}
static void HandleDebug(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
PrintError(js, "Must specify a subcommand");
@@ -295,8 +494,11 @@ static void HandleDebug(Isolate* isolate, JSONStream* js) {
} else if (js->num_arguments() == 3) {
// Print individual breakpoint.
intptr_t id = atoi(js->GetArgument(2));
SourceBreakpoint* bpt = isolate->debugger()->GetBreakpointById(id);
intptr_t id = 0;
SourceBreakpoint* bpt = NULL;
if (GetIntegerId(js->GetArgument(2), &id)) {
bpt = isolate->debugger()->GetBreakpointById(id);
}
if (bpt != NULL) {
bpt->PrintToJSONStream(js);
} else {
@@ -324,10 +526,12 @@ static ServiceMessageHandlerEntry __message_handlers[] = {
{ "classes", HandleClasses },
{ "cpu", HandleCpu },
{ "debug", HandleDebug },
{ "libraries", HandleLibraries },
{ "library", HandleLibrary },
{ "name", HandleName },
{ "objecthistogram", HandleObjectHistogram},
{ "objects", HandleObjects },
{ "scripts", HandleScripts },
{ "stacktrace", HandleStackTrace },
};
+212
View File
@@ -54,6 +54,58 @@ static RawInstance* Eval(Dart_Handle lib, const char* expr) {
}
static RawInstance* EvalF(Dart_Handle lib, const char* fmt, ...) {
Isolate* isolate = Isolate::Current();
va_list args;
va_start(args, fmt);
intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
va_end(args);
char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
va_list args2;
va_start(args2, fmt);
OS::VSNPrint(buffer, (len + 1), fmt, args2);
va_end(args2);
return Eval(lib, buffer);
}
/*
static RawFunction* GetFunction(const Class& cls, const char* name) {
const Function& result = Function::Handle(cls.LookupDynamicFunction(
String::Handle(String::New(name))));
EXPECT(!result.IsNull());
return result.raw();
}
static RawFunction* GetStaticFunction(const Class& cls, const char* name) {
const Function& result = Function::Handle(cls.LookupStaticFunction(
String::Handle(String::New(name))));
EXPECT(!result.IsNull());
return result.raw();
}
static RawField* GetField(const Class& cls, const char* name) {
const Field& field =
Field::Handle(cls.LookupField(String::Handle(String::New(name))));
EXPECT(!field.IsNull());
return field.raw();
}
*/
static RawClass* GetClass(const Library& lib, const char* name) {
const Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New(name))));
EXPECT(!cls.IsNull()); // No ambiguity error expected.
return cls.raw();
}
TEST_CASE(Service_DebugBreakpoints) {
const char* kScript =
"var port;\n" // Set to our mock port by C++.
@@ -146,4 +198,164 @@ TEST_CASE(Service_DebugBreakpoints) {
handler.msg());
}
TEST_CASE(Service_Classes) {
const char* kScript =
"var port;\n" // Set to our mock port by C++.
"\n"
"class A {\n"
" var a;\n"
" dynamic b() {}\n"
" dynamic c() {\n"
" var d = () { b(); };\n"
" return d;\n"
" }\n"
"}\n"
"main() {\n"
" var z = new A();\n"
" var x = z.c();\n"
" x();\n"
"}";
Isolate* isolate = Isolate::Current();
Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
EXPECT_VALID(h_lib);
Library& lib = Library::Handle();
lib ^= Api::UnwrapHandle(h_lib);
EXPECT(!lib.IsNull());
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
const Class& class_a = Class::Handle(GetClass(lib, "A"));
EXPECT(!class_a.IsNull());
intptr_t cid = class_a.id();
// Build a mock message handler and wrap it in a dart port.
ServiceTestMessageHandler handler;
Dart_Port port_id = PortMap::CreatePort(&handler);
Dart_Handle port =
Api::NewHandle(isolate, DartLibraryCalls::NewSendPort(port_id));
EXPECT_VALID(port);
EXPECT_VALID(Dart_SetField(h_lib, NewString("port"), port));
Instance& service_msg = Instance::Handle();
// Request an invalid class id.
service_msg = Eval(h_lib, "[port, ['classes', '999999'], [], []]");
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"999999 is not a valid class id.\","
"\"message\":{\"arguments\":[\"classes\",\"999999\"],"
"\"option_keys\":[],\"option_values\":[]}}", handler.msg());
// Request the class A over the service.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "'], [], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Class\",\"id\":\"classes\\/1009\",\"name\":\"A\","
"\"user_name\":\"A\",\"implemented\":false,\"abstract\":false,"
"\"patch\":false,\"finalized\":true,\"const\":false,\"super\":"
"{\"type\":\"@Class\",\"id\":\"classes\\/35\",\"name\":\"Object\","
"\"user_name\":\"Object\"},\"library\":{\"type\":\"@Library\",\"id\":"
"\"libraries\\/12\",\"name\":\"\",\"user_name\":\"dart:test-lib\"},"
"\"fields\":[{\"type\":\"@Field\",\"id\":\"classes\\/1009\\/fields\\/0\","
"\"name\":\"a\",\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\","
"\"id\":\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"},"
"\"declared_type\":{\"type\":\"@Class\",\"id\":\"classes\\/106\","
"\"name\":\"dynamic\",\"user_name\":\"dynamic\"},\"static\":false,"
"\"final\":false,\"const\":false}],\"functions\":["
"{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/0\","
"\"name\":\"get:a\",\"user_name\":\"A.a\"},{\"type\":\"@Function\","
"\"id\":\"classes\\/1009\\/functions\\/1\",\"name\":\"set:a\","
"\"user_name\":\"A.a=\"},{\"type\":\"@Function\",\"id\":"
"\"classes\\/1009\\/functions\\/2\",\"name\":\"b\",\"user_name\":\"A.b\"}"
",{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/3\","
"\"name\":\"c\",\"user_name\":\"A.c\"},{\"type\":\"@Function\",\"id\":"
"\"classes\\/1009\\/functions\\/4\",\"name\":\"A.\",\"user_name\":"
"\"A.A\"}]}",
handler.msg());
// Request function 0 from class A.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '0'],"
"[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Function\",\"id\":\"classes\\/1009\\/functions\\/0\",\"name\":"
"\"get:a\",\"user_name\":\"A.a\",\"is_static\":false,\"is_const\":false,"
"\"is_optimizable\":true,\"is_inlinable\":false,\"kind\":"
"\"implicit getter\",\"unoptimized_code\":{\"type\":\"null\"},"
"\"usage_counter\":0,\"optimized_call_site_count\":0,\"code\":"
"{\"type\":\"null\"},\"deoptimizations\":0}", handler.msg());
// Request field 0 from class A.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '0'],"
"[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Field\",\"id\":\"classes\\/1009\\/fields\\/0\",\"name\":\"a\","
"\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\",\"id\":"
"\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"},\"declared_type\":"
"{\"type\":\"@Class\",\"id\":\"classes\\/106\",\"name\":\"dynamic\","
"\"user_name\":\"dynamic\"},\"static\":false,\"final\":false,\"const\":"
"false,\"guard_nullable\":true,\"guard_class\":{\"type\":\"@Class\","
"\"id\":\"classes\\/105\",\"name\":\"Null\",\"user_name\":\"Null\"},"
"\"guard_length\":\"variable\"}", handler.msg());
// Invalid sub command.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'huh', '0'],"
"[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"Invalid sub collection huh\",\"message\":"
"{\"arguments\":[\"classes\",\"1009\",\"huh\",\"0\"],\"option_keys\":[],"
"\"option_values\":[]}}", handler.msg());
// Invalid field request.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9'],"
"[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"fields id (9) must be in [0, 1).\","
"\"message\":{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\"],"
"\"option_keys\":[],\"option_values\":[]}}", handler.msg());
// Invalid function request.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9'],"
"[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"functions id (9) must be in [0, 5).\","
"\"message\":{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\"],"
"\"option_keys\":[],\"option_values\":[]}}", handler.msg());
// Invalid field subcommand.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9', 'x']"
",[], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":"
"{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\",\"x\"],"
"\"option_keys\":[],\"option_values\":[]}}",
handler.msg());
// Invalid function request.
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9',"
"'x'], [], []]", cid);
Service::HandleServiceMessage(isolate, service_msg);
handler.HandleNextMessage();
EXPECT_STREQ(
"{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":"
"{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\",\"x\"],"
"\"option_keys\":[],\"option_values\":[]}}",
handler.msg());
}
} // namespace dart
@@ -10,16 +10,16 @@ import 'package:expect/expect.dart';
class NullCollectionTest extends VmServiceRequestHelper {
NullCollectionTest(port, id, collection) :
super('http://127.0.0.1:$port/isolates/$id/$collection/9999999');
super('http://127.0.0.1:$port/$id/$collection/9999999');
onRequestCompleted(Map reply) {
Expect.equals('null', reply['type']);
Expect.equals('Error', reply['type']);
}
}
class BadCollectionTest extends VmServiceRequestHelper {
BadCollectionTest(port, id, collection) :
super('http://127.0.0.1:$port/isolates/$id/$collection');
super('http://127.0.0.1:$port/$id/$collection');
onRequestCompleted(Map reply) {
Expect.equals('Error', reply['type']);
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class NullCollectionTest extends VmServiceRequestHelper {
NullCollectionTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/objects/50');
super('http://127.0.0.1:$port/$id/objects/50');
onRequestCompleted(Map reply) {
Expect.equals('null', reply['type']);
@@ -19,7 +19,7 @@ class NullCollectionTest extends VmServiceRequestHelper {
class BadCollectionTest extends VmServiceRequestHelper {
BadCollectionTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/objects');
super('http://127.0.0.1:$port/$id/objects');
onRequestCompleted(Map reply) {
Expect.equals('Error', reply['type']);
@@ -140,7 +140,7 @@ class BadBananaClassTest {
class ClassTableTest extends VmServiceRequestHelper {
ClassTableTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/classes/');
super('http://127.0.0.1:$port/$id/classes/');
int banana_class_id;
int bad_banana_class_id;
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class ClassTest extends VmServiceRequestHelper {
ClassTest(port, id, classId) :
super('http://127.0.0.1:$port/isolates/$id/classes/$classId');
super('http://127.0.0.1:$port/$id/$classId');
onRequestCompleted(Map reply) {
Expect.equals('Class', reply['type']);
@@ -22,7 +22,7 @@ class ClassTest extends VmServiceRequestHelper {
class LibraryTest extends VmServiceRequestHelper {
LibraryTest(port, id, libId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$libId');
super('http://127.0.0.1:$port/$id/$libId');
int _classId;
onRequestCompleted(Map reply) {
@@ -37,7 +37,7 @@ class LibraryTest extends VmServiceRequestHelper {
class RootLibraryTest extends VmServiceRequestHelper {
RootLibraryTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/library');
super('http://127.0.0.1:$port/$id/library');
int _libId;
onRequestCompleted(Map reply) {
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class CodeATest extends VmServiceRequestHelper {
CodeATest(port, id, codeId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$codeId');
super('http://127.0.0.1:$port/$id/$codeId');
onRequestCompleted(Map reply) {
Expect.equals('Code', reply['type']);
@@ -21,7 +21,7 @@ class CodeATest extends VmServiceRequestHelper {
class CodeCTest extends VmServiceRequestHelper {
CodeCTest(port, id, codeId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$codeId');
super('http://127.0.0.1:$port/$id/$codeId');
onRequestCompleted(Map reply) {
Expect.equals('Code', reply['type']);
@@ -32,7 +32,7 @@ class CodeCTest extends VmServiceRequestHelper {
class StackTraceTest extends VmServiceRequestHelper {
StackTraceTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/stacktrace');
super('http://127.0.0.1:$port/$id/stacktrace');
int _aId;
int _cId;
@@ -9,7 +9,7 @@ import 'package:expect/expect.dart';
class EchoRequestTest extends VmServiceRequestHelper {
EchoRequestTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/_echo/foo/bar?a=b&k=&d=e&z=w');
super('http://127.0.0.1:$port/$id/_echo/foo/bar?a=b&k=&d=e&z=w');
onRequestCompleted(Map reply) {
Expect.equals('message', reply['type']);
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class MethodTest extends VmServiceRequestHelper {
MethodTest(port, id, functionId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$functionId');
super('http://127.0.0.1:$port/$id/$functionId');
onRequestCompleted(Map reply) {
Expect.equals('Function', reply['type']);
Expect.equals('C.c', reply['user_name']);
@@ -20,7 +20,7 @@ class MethodTest extends VmServiceRequestHelper {
class FunctionTest extends VmServiceRequestHelper {
FunctionTest(port, id, functionId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$functionId');
super('http://127.0.0.1:$port/$id/$functionId');
onRequestCompleted(Map reply) {
Expect.equals('Function', reply['type']);
@@ -31,7 +31,7 @@ class FunctionTest extends VmServiceRequestHelper {
class StackTraceTest extends VmServiceRequestHelper {
StackTraceTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/stacktrace');
super('http://127.0.0.1:$port/$id/stacktrace');
int _aId;
int _cId;
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class LibraryTest extends VmServiceRequestHelper {
LibraryTest(port, id, libId) :
super('http://127.0.0.1:$port/isolates/$id/objects/$libId');
super('http://127.0.0.1:$port/$id/$libId');
onRequestCompleted(Map reply) {
Expect.equals('Library', reply['type']);
@@ -20,7 +20,7 @@ class LibraryTest extends VmServiceRequestHelper {
class RootLibraryTest extends VmServiceRequestHelper {
RootLibraryTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/library');
super('http://127.0.0.1:$port/$id/library');
int _libId;
onRequestCompleted(Map reply) {
@@ -9,7 +9,7 @@ import 'package:expect/expect.dart';
class StacktraceTest extends VmServiceRequestHelper {
StacktraceTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/stacktrace');
super('http://127.0.0.1:$port/$id/stacktrace');
onRequestCompleted(Map reply) {
Expect.equals('StackTrace', reply['type'], 'Not a StackTrace message.');
+2 -2
View File
@@ -255,7 +255,7 @@ class ClassTableHelper {
class FieldRequestHelper extends VmServiceRequestHelper {
FieldRequestHelper(port, isolate_id, field_id) :
super('http://127.0.0.1:$port/isolates/$isolate_id/objects/$field_id');
super('http://127.0.0.1:$port/$isolate_id/$field_id');
Map field;
onRequestCompleted(Map reply) {
Expect.equals('Field', reply['type']);
@@ -269,7 +269,7 @@ class ClassFieldRequestHelper extends VmServiceRequestHelper {
int port_;
int isolate_id_;
ClassFieldRequestHelper(port, isolate_id, class_id, this.fieldNames) :
super('http://127.0.0.1:$port/isolates/$isolate_id/classes/$class_id') {
super('http://127.0.0.1:$port/$isolate_id/$class_id') {
port_ = port;
isolate_id_ = isolate_id;
}
@@ -10,7 +10,7 @@ import 'package:expect/expect.dart';
class ClassTableTest extends VmServiceRequestHelper {
ClassTableTest(port, id) :
super('http://127.0.0.1:$port/isolates/$id/classes');
super('http://127.0.0.1:$port/$id/classes');
onRequestCompleted(Map reply) {
ClassTableHelper helper = new ClassTableHelper(reply);