Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(886)

Side by Side Diff: runtime/bin/vmservice/client/lib/src/service/object.dart

Issue 381383010: Add breakpoints and single-stepping to Observatory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix bugs, gen js Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/elements/script_inset.html ('k') | runtime/vm/debugger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of service; 5 part of service;
6 6
7 /// A [ServiceObject] is an object known to the VM service and is tied 7 /// A [ServiceObject] is an object known to the VM service and is tied
8 /// to an owning [Isolate]. 8 /// to an owning [Isolate].
9 abstract class ServiceObject extends Observable { 9 abstract class ServiceObject extends Observable {
10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 break; 81 break;
82 case 'Function': 82 case 'Function':
83 obj = new ServiceFunction._empty(owner); 83 obj = new ServiceFunction._empty(owner);
84 break; 84 break;
85 case 'Isolate': 85 case 'Isolate':
86 obj = new Isolate._empty(owner.vm); 86 obj = new Isolate._empty(owner.vm);
87 break; 87 break;
88 case 'Library': 88 case 'Library':
89 obj = new Library._empty(owner); 89 obj = new Library._empty(owner);
90 break; 90 break;
91 case 'Null':
92 return null;
93 case 'ServiceError': 91 case 'ServiceError':
94 obj = new ServiceError._empty(owner); 92 obj = new ServiceError._empty(owner);
95 break; 93 break;
96 case 'ServiceEvent': 94 case 'ServiceEvent':
97 obj = new ServiceEvent._empty(owner); 95 obj = new ServiceEvent._empty(owner);
98 break; 96 break;
99 case 'ServiceException': 97 case 'ServiceException':
100 obj = new ServiceException._empty(owner); 98 obj = new ServiceException._empty(owner);
101 break; 99 break;
102 case 'Script': 100 case 'Script':
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 map = _parseJSON(eventMessage); 259 map = _parseJSON(eventMessage);
262 } catch (e, st) { 260 } catch (e, st) {
263 Logger.root.severe('Ignoring malformed event message: ${eventMessage}'); 261 Logger.root.severe('Ignoring malformed event message: ${eventMessage}');
264 return; 262 return;
265 } 263 }
266 if (map['type'] != 'ServiceEvent') { 264 if (map['type'] != 'ServiceEvent') {
267 Logger.root.severe( 265 Logger.root.severe(
268 "Expected 'ServiceEvent' but found '${map['type']}'"); 266 "Expected 'ServiceEvent' but found '${map['type']}'");
269 return; 267 return;
270 } 268 }
269
271 // Extract the owning isolate from the event itself. 270 // Extract the owning isolate from the event itself.
272 String owningIsolateId = map['isolate']['id']; 271 String owningIsolateId = map['isolate']['id'];
273 _getIsolate(owningIsolateId).then((owningIsolate) { 272 _getIsolate(owningIsolateId).then((owningIsolate) {
274 var event = new ServiceObject._fromMap(owningIsolate, map); 273 var event = new ServiceObject._fromMap(owningIsolate, map);
275 events.add(event); 274 events.add(event);
276 }); 275 });
277 } 276 }
278 277
279 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); 278 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+');
280 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+/'); 279 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+/');
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 'message': 'Could not decode JSON: $e', 408 'message': 'Could not decode JSON: $e',
410 }))); 409 })));
411 } 410 }
412 411
413 /// Gets [id] as an [ObservableMap] from the service directly. If 412 /// Gets [id] as an [ObservableMap] from the service directly. If
414 /// an error occurs, the future is completed as an error with a 413 /// an error occurs, the future is completed as an error with a
415 /// ServiceError or ServiceException. Therefore any chained then() calls 414 /// ServiceError or ServiceException. Therefore any chained then() calls
416 /// will only receive a map encoding a valid ServiceObject. 415 /// will only receive a map encoding a valid ServiceObject.
417 Future<ObservableMap> getAsMap(String id) { 416 Future<ObservableMap> getAsMap(String id) {
418 return getString(id).then((response) { 417 return getString(id).then((response) {
418 print("GOT $response");
koda 2014/07/29 15:55:12 Seems you left some debug printing here. But this
Cutch 2014/07/29 17:04:35 We have the logging package for this. It's easy to
419 var map = _parseJSON(response); 419 var map = _parseJSON(response);
420 return _processMap(map); 420 return _processMap(map);
421 }).catchError((error) { 421 }).catchError((error) {
422 // ServiceError, forward to VM's ServiceError stream. 422 // ServiceError, forward to VM's ServiceError stream.
423 errors.add(error); 423 errors.add(error);
424 return new Future.error(error); 424 return new Future.error(error);
425 }, test: (e) => e is ServiceError).catchError((exception) { 425 }, test: (e) => e is ServiceError).catchError((exception) {
426 // ServiceException, forward to VM's ServiceException stream. 426 // ServiceException, forward to VM's ServiceException stream.
427 exceptions.add(exception); 427 exceptions.add(exception);
428 return new Future.error(exception); 428 return new Future.error(exception);
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 void _update(ObservableMap map, bool mapIsRef) { 747 void _update(ObservableMap map, bool mapIsRef) {
748 mainPort = map['mainPort']; 748 mainPort = map['mainPort'];
749 name = map['name']; 749 name = map['name'];
750 vmName = map['name']; 750 vmName = map['name'];
751 if (mapIsRef) { 751 if (mapIsRef) {
752 return; 752 return;
753 } 753 }
754 _loaded = true; 754 _loaded = true;
755 loading = false; 755 loading = false;
756 756
757 reloadBreakpoints();
758
757 // Remap DebuggerEvent to ServiceEvent so that the observatory can 759 // Remap DebuggerEvent to ServiceEvent so that the observatory can
758 // work against 1.5 vms in the short term. 760 // work against 1.5 vms in the short term.
759 // 761 //
760 // TODO(turnidge): Remove this when no longer needed. 762 // TODO(turnidge): Remove this when no longer needed.
761 var pause = map['pauseEvent']; 763 var pause = map['pauseEvent'];
762 if (pause != null) { 764 if (pause != null) {
763 if (pause['type'] == 'DebuggerEvent') { 765 if (pause['type'] == 'DebuggerEvent') {
764 pause['type'] = 'ServiceEvent'; 766 pause['type'] = 'ServiceEvent';
765 } 767 }
766 } 768 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 // Number of children. 885 // Number of children.
884 var children = _trieData[_trieDataCursor++]; 886 var children = _trieData[_trieDataCursor++];
885 // Recursively read child nodes. 887 // Recursively read child nodes.
886 for (var i = 0; i < children; i++) { 888 for (var i = 0; i < children; i++) {
887 var child = _readTrieNode(codeTable); 889 var child = _readTrieNode(codeTable);
888 node.children.add(child); 890 node.children.add(child);
889 node.summedChildCount += child.count; 891 node.summedChildCount += child.count;
890 } 892 }
891 return node; 893 return node;
892 } 894 }
895
896 ServiceMap breakpoints;
897
898 void _removeBreakpoint(ServiceMap bpt) {
899 var script = bpt['location']['script'];
900 var tokenPos = bpt['location']['tokenPos'];
901 assert(tokenPos != null);
902 if (script.loaded) {
903 var line = script.tokenToLine(tokenPos);
904 assert(line != null);
905 assert(script.lines[line - 1].bpt == bpt);
906 script.lines[line - 1].bpt = null;
907 }
908 }
909
910 void _addBreakpoint(ServiceMap bpt) {
911 var script = bpt['location']['script'];
912 var tokenPos = bpt['location']['tokenPos'];
913 assert(tokenPos != null);
914 if (script.loaded) {
915 var line = script.tokenToLine(tokenPos);
916 assert(line != null);
917 assert(script.lines[line - 1].bpt == null);
918 script.lines[line - 1].bpt = bpt;
919 } else {
920 // Load the script and then plop in the breakpoint.
921 script.load().then((_) {
922 _addBreakpoint(bpt);
923 });
924 }
925 }
926
927 void _updateBreakpoints(ServiceMap newBreakpoints) {
928 // Remove all of the old breakpoints from the Script lines.
929 if (breakpoints != null) {
930 for (var bpt in breakpoints['breakpoints']) {
931 _removeBreakpoint(bpt);
932 }
933 }
934 // Add all of the new breakpoints to the Script lines.
935 for (var bpt in newBreakpoints['breakpoints']) {
936 _addBreakpoint(bpt);
937 }
938 breakpoints = newBreakpoints;
939 }
940
941 Future<ServiceObject> _inProgressReloadBpts;
942
943 Future reloadBreakpoints() {
944 // TODO(turnidge): Can reusing the Future here ever cause us to
945 // get stale breakpoints?
946 if (_inProgressReloadBpts == null) {
947 _inProgressReloadBpts =
948 get('debug/breakpoints').then((newBpts) {
949 _updateBreakpoints(newBpts);
950 }).whenComplete(() {
951 _inProgressReloadBpts = null;
952 });
953 }
954 return _inProgressReloadBpts;
955 }
956
957 Future<ServiceObject> setBreakpoint(Script script, int line) {
958 return get(script.id + "/setBreakpoint?line=${line}").then((result) {
959 if (result is DartError) {
960 // Unable to set a breakpoint at desired line.
961 script.lines[line - 1].possibleBpt = false;
962 }
963 return reloadBreakpoints();
964 });
965 }
966
967 Future clearBreakpoint(ServiceMap bpt) {
968 return get('${bpt.id}/clear').then((result) {
969 if (result is DartError) {
970 // TODO(turnidge): Handle this more gracefully.
971 Logger.root.severe(result.message);
972 }
973 if (pauseEvent != null &&
974 pauseEvent.breakpoint != null &&
975 (pauseEvent.breakpoint['id'] == bpt['id'])) {
976 return isolate.reload();
977 } else {
978 return reloadBreakpoints();
979 }
980 });
981 }
982
983 Future pause() {
984 return get("debug/pause").then((result) {
985 if (result is DartError) {
986 // TODO(turnidge): Handle this more gracefully.
987 Logger.root.severe(result.message);
988 }
989 return isolate.reload();
990 });
991 }
992
993 Future resume() {
994 return get("debug/resume").then((result) {
995 if (result is DartError) {
996 // TODO(turnidge): Handle this more gracefully.
997 Logger.root.severe(result.message);
998 }
999 return isolate.reload();
1000 });
1001 }
1002
1003 Future stepInto() {
1004 print('isolate.stepInto');
1005 return get("debug/resume?step=into").then((result) {
1006 if (result is DartError) {
1007 // TODO(turnidge): Handle this more gracefully.
1008 Logger.root.severe(result.message);
1009 }
1010 return isolate.reload();
1011 });
1012 }
1013
1014 Future stepOver() {
1015 return get("debug/resume?step=over").then((result) {
1016 if (result is DartError) {
1017 // TODO(turnidge): Handle this more gracefully.
1018 Logger.root.severe(result.message);
1019 }
1020 return isolate.reload();
1021 });
1022 }
1023
1024 Future stepOut() {
1025 return get("debug/resume?step=out").then((result) {
1026 if (result is DartError) {
1027 // TODO(turnidge): Handle this more gracefully.
1028 Logger.root.severe(result.message);
1029 }
1030 return isolate.reload();
1031 });
1032 }
893 } 1033 }
894 1034
895 /// A [ServiceObject] which implements [ObservableMap]. 1035 /// A [ServiceObject] which implements [ObservableMap].
896 class ServiceMap extends ServiceObject implements ObservableMap { 1036 class ServiceMap extends ServiceObject implements ObservableMap {
897 final ObservableMap _map = new ObservableMap(); 1037 final ObservableMap _map = new ObservableMap();
898 static String objectIdRingPrefix = 'objects/'; 1038 static String objectIdRingPrefix = 'objects/';
899 1039
900 bool get canCache { 1040 bool get canCache {
901 return (_serviceType == 'Class' || 1041 return (_serviceType == 'Class' ||
902 _serviceType == 'Function' || 1042 _serviceType == 'Function' ||
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 isDart = !kind.isFake(); 1440 isDart = !kind.isFake();
1301 1441
1302 if (mapIsRef) { return; } 1442 if (mapIsRef) { return; }
1303 1443
1304 isStatic = map['isStatic']; 1444 isStatic = map['isStatic'];
1305 isConst = map['isConst']; 1445 isConst = map['isConst'];
1306 parent = map['parent']; 1446 parent = map['parent'];
1307 script = map['script']; 1447 script = map['script'];
1308 tokenPos = map['tokenPos']; 1448 tokenPos = map['tokenPos'];
1309 endTokenPos = map['endTokenPos']; 1449 endTokenPos = map['endTokenPos'];
1310 code = map['code']; 1450 code = _convertNull(map['code']);
1311 unoptimizedCode = map['unoptimized_code']; 1451 unoptimizedCode = _convertNull(map['unoptimized_code']);
1312 isOptimizable = map['is_optimizable']; 1452 isOptimizable = map['is_optimizable'];
1313 isInlinable = map['is_inlinable']; 1453 isInlinable = map['is_inlinable'];
1314 deoptimizations = map['deoptimizations']; 1454 deoptimizations = map['deoptimizations'];
1315 usageCounter = map['usage_counter']; 1455 usageCounter = map['usage_counter'];
1316 1456
1317 if (parent == null) { 1457 if (parent == null) {
1318 qualifiedName = (owningClass != null) ? 1458 qualifiedName = (owningClass != null) ?
1319 "${owningClass.name}.${name}" : 1459 "${owningClass.name}.${name}" :
1320 name; 1460 name;
1321 } else { 1461 } else {
1322 qualifiedName = "${parent.qualifiedName}.${name}"; 1462 qualifiedName = "${parent.qualifiedName}.${name}";
1323 } 1463 }
1324 1464
1325 } 1465 }
1326 } 1466 }
1327 1467
1328 class ScriptLine extends Observable { 1468 class ScriptLine extends Observable {
1469 final Script script;
1329 final int line; 1470 final int line;
1330 final String text; 1471 final String text;
1331 @observable int hits; 1472 @observable int hits;
1332 ScriptLine(this.line, this.text); 1473 @observable ServiceMap bpt;
1474 @observable bool possibleBpt = true;
1475
1476 static bool _isTrivialToken(String token) {
1477 if (token == 'else') {
1478 return true;
1479 }
1480 for (var c in token.split('')) {
1481 switch (c) {
1482 case '{':
1483 case '}':
1484 case '(':
1485 case ')':
1486 case ';':
1487 break;
1488 default:
1489 return false;
1490 }
1491 }
1492 return true;
1493 }
1494
1495 static bool _isTrivialLine(String text) {
1496 var wsTokens = text.split(new RegExp(r"(\s)+"));
1497 for (var wsToken in wsTokens) {
1498 var tokens = wsToken.split(new RegExp(r"(\b)"));
1499 for (var token in tokens) {
1500 if (!_isTrivialToken(token)) {
1501 return false;
1502 }
1503 }
1504 }
1505 return true;
1506 }
1507
1508 ScriptLine(this.script, this.line, this.text) {
1509 possibleBpt = !_isTrivialLine(text);
1510
1511 // TODO(turnidge): This is not so efficient. Consider improving.
1512 for (var bpt in this.script.isolate.breakpoints['breakpoints']) {
1513 var bptScript = bpt['location']['script'];
1514 var bptTokenPos = bpt['location']['tokenPos'];
1515 if (bptScript == this.script &&
1516 bptScript.tokenToLine(bptTokenPos) == line) {
1517 this.bpt = bpt;
1518 }
1519 }
1520 }
1333 } 1521 }
1334 1522
1335 class Script extends ServiceObject with Coverage { 1523 class Script extends ServiceObject with Coverage {
1336 final lines = new ObservableList<ScriptLine>(); 1524 final lines = new ObservableList<ScriptLine>();
1337 final _hits = new Map<int, int>(); 1525 final _hits = new Map<int, int>();
1338 @observable String kind; 1526 @observable String kind;
1339 @observable int firstTokenPos; 1527 @observable int firstTokenPos;
1340 @observable int lastTokenPos; 1528 @observable int lastTokenPos;
1341 @observable Library owningLibrary; 1529 @observable Library owningLibrary;
1342 bool get canCache => true; 1530 bool get canCache => true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 } 1564 }
1377 1565
1378 void _parseTokenPosTable(List<List<int>> table) { 1566 void _parseTokenPosTable(List<List<int>> table) {
1379 if (table == null) { 1567 if (table == null) {
1380 return; 1568 return;
1381 } 1569 }
1382 _tokenToLine.clear(); 1570 _tokenToLine.clear();
1383 _tokenToCol.clear(); 1571 _tokenToCol.clear();
1384 firstTokenPos = null; 1572 firstTokenPos = null;
1385 lastTokenPos = null; 1573 lastTokenPos = null;
1574 var lineSet = new Set();
1575
1386 for (var line in table) { 1576 for (var line in table) {
1387 // Each entry begins with a line number... 1577 // Each entry begins with a line number...
1388 var lineNumber = line[0]; 1578 var lineNumber = line[0];
1579 lineSet.add(lineNumber);
1389 for (var pos = 1; pos < line.length; pos += 2) { 1580 for (var pos = 1; pos < line.length; pos += 2) {
1390 // ...and is followed by (token offset, col number) pairs. 1581 // ...and is followed by (token offset, col number) pairs.
1391 var tokenOffset = line[pos]; 1582 var tokenOffset = line[pos];
1392 var colNumber = line[pos+1]; 1583 var colNumber = line[pos+1];
1393 if (firstTokenPos == null) { 1584 if (firstTokenPos == null) {
1394 // Mark first token position. 1585 // Mark first token position.
1395 firstTokenPos = tokenOffset; 1586 firstTokenPos = tokenOffset;
1396 lastTokenPos = tokenOffset; 1587 lastTokenPos = tokenOffset;
1397 } else { 1588 } else {
1398 // Keep track of max and min token positions. 1589 // Keep track of max and min token positions.
1399 firstTokenPos = (firstTokenPos <= tokenOffset) ? 1590 firstTokenPos = (firstTokenPos <= tokenOffset) ?
1400 firstTokenPos : tokenOffset; 1591 firstTokenPos : tokenOffset;
1401 lastTokenPos = (lastTokenPos >= tokenOffset) ? 1592 lastTokenPos = (lastTokenPos >= tokenOffset) ?
1402 lastTokenPos : tokenOffset; 1593 lastTokenPos : tokenOffset;
1403 } 1594 }
1404 _tokenToLine[tokenOffset] = lineNumber; 1595 _tokenToLine[tokenOffset] = lineNumber;
1405 _tokenToCol[tokenOffset] = colNumber; 1596 _tokenToCol[tokenOffset] = colNumber;
1406 } 1597 }
1407 } 1598 }
1599
1600 for (var line in lines) {
1601 // Remove possible breakpoints on lines with no tokens.
1602 if (!lineSet.contains(line.line)) {
1603 line.possibleBpt = false;
1604 }
1605 }
1408 } 1606 }
1409 1607
1410 void _processHits(List scriptHits) { 1608 void _processHits(List scriptHits) {
1411 // Update hits table. 1609 // Update hits table.
1412 for (var i = 0; i < scriptHits.length; i += 2) { 1610 for (var i = 0; i < scriptHits.length; i += 2) {
1413 var line = scriptHits[i]; 1611 var line = scriptHits[i];
1414 var hit = scriptHits[i + 1]; // hit status. 1612 var hit = scriptHits[i + 1]; // hit status.
1415 assert(line >= 1); // Lines start at 1. 1613 assert(line >= 1); // Lines start at 1.
1416 var oldHits = _hits[line]; 1614 var oldHits = _hits[line];
1417 if (oldHits != null) { 1615 if (oldHits != null) {
(...skipping 12 matching lines...) Expand all
1430 } 1628 }
1431 var sourceLines = source.split('\n'); 1629 var sourceLines = source.split('\n');
1432 if (sourceLines.length == 0) { 1630 if (sourceLines.length == 0) {
1433 return; 1631 return;
1434 } 1632 }
1435 // We have the source to the script. This is now loaded. 1633 // We have the source to the script. This is now loaded.
1436 _loaded = true; 1634 _loaded = true;
1437 lines.clear(); 1635 lines.clear();
1438 Logger.root.info('Adding ${sourceLines.length} source lines for ${_url}'); 1636 Logger.root.info('Adding ${sourceLines.length} source lines for ${_url}');
1439 for (var i = 0; i < sourceLines.length; i++) { 1637 for (var i = 0; i < sourceLines.length; i++) {
1440 lines.add(new ScriptLine(i + 1, sourceLines[i])); 1638 lines.add(new ScriptLine(this, i + 1, sourceLines[i]));
1441 } 1639 }
1442 _applyHitsToLines(); 1640 _applyHitsToLines();
1443 } 1641 }
1444 1642
1445 void _applyHitsToLines() { 1643 void _applyHitsToLines() {
1446 if (lines.length == 0) {
1447 return;
1448 }
1449 for (var line in lines) { 1644 for (var line in lines) {
1450 var hits = _hits[line.line]; 1645 var hits = _hits[line.line];
1451 line.hits = hits; 1646 line.hits = hits;
1452 } 1647 }
1453 } 1648 }
1454 } 1649 }
1455 1650
1456 class CodeTick { 1651 class CodeTick {
1457 final int address; 1652 final int address;
1458 final int exclusiveTicks; 1653 final int exclusiveTicks;
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1983 localAddress = map['localAddress']; 2178 localAddress = map['localAddress'];
1984 localPort = map['localPort']; 2179 localPort = map['localPort'];
1985 remoteAddress = map['remoteAddress']; 2180 remoteAddress = map['remoteAddress'];
1986 remotePort = map['remotePort']; 2181 remotePort = map['remotePort'];
1987 2182
1988 fd = map['fd']; 2183 fd = map['fd'];
1989 socketOwner = map['owner']; 2184 socketOwner = map['owner'];
1990 } 2185 }
1991 } 2186 }
1992 2187
2188 // Convert any ServiceMaps representing a null instance into an actual null.
2189 _convertNull(obj) {
2190 if (obj is ServiceMap &&
2191 obj.serviceType == 'Null') {
2192 return null;
2193 }
2194 return obj;
2195 }
2196
1993 // Returns true if [map] is a service map. i.e. it has the following keys: 2197 // Returns true if [map] is a service map. i.e. it has the following keys:
1994 // 'id' and a 'type'. 2198 // 'id' and a 'type'.
1995 bool _isServiceMap(ObservableMap m) { 2199 bool _isServiceMap(ObservableMap m) {
1996 return (m != null) && (m['id'] != null) && (m['type'] != null); 2200 return (m != null) && (m['id'] != null) && (m['type'] != null);
1997 } 2201 }
1998 2202
1999 bool _hasRef(String type) => type.startsWith('@'); 2203 bool _hasRef(String type) => type.startsWith('@');
2000 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type); 2204 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type);
2001 2205
2002 /// Recursively upgrades all [ServiceObject]s inside [collection] which must 2206 /// Recursively upgrades all [ServiceObject]s inside [collection] which must
(...skipping 27 matching lines...) Expand all
2030 var v = list[i]; 2234 var v = list[i];
2031 if ((v is ObservableMap) && _isServiceMap(v)) { 2235 if ((v is ObservableMap) && _isServiceMap(v)) {
2032 list[i] = owner.getFromMap(v); 2236 list[i] = owner.getFromMap(v);
2033 } else if (v is ObservableList) { 2237 } else if (v is ObservableList) {
2034 _upgradeObservableList(v, owner); 2238 _upgradeObservableList(v, owner);
2035 } else if (v is ObservableMap) { 2239 } else if (v is ObservableMap) {
2036 _upgradeObservableMap(v, owner); 2240 _upgradeObservableMap(v, owner);
2037 } 2241 }
2038 } 2242 }
2039 } 2243 }
OLDNEW
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/elements/script_inset.html ('k') | runtime/vm/debugger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698