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

Side by Side Diff: tool/input_sdk/private/debugger.dart

Issue 1997473007: Fix debugger (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | tool/sdk_expected_errors.txt » ('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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library dart._debugger; 5 library dart._debugger;
6 6
7 import 'dart:_foreign_helper' show JS; 7 import 'dart:_foreign_helper' show JS;
8 import 'dart:_runtime' as dart; 8 import 'dart:_runtime' as dart;
9 import 'dart:core'; 9 import 'dart:core';
10 import 'dart:collection';
11 import 'dart:html' as html;
vsm 2016/05/20 01:30:39 Nothing in dart:core, etc depends on debugger, rig
Jacob 2016/05/20 17:02:36 Nothing depends on the _debugger library. The only
10 12
11 /// Config object to pass to devtools to signal that an object should not be 13 /// Config object to pass to devtools to signal that an object should not be
12 /// formatted by the Dart formatter. This is used to specify that an Object 14 /// formatted by the Dart formatter. This is used to specify that an Object
13 /// should just be displayed using the regular JavaScript view instead of a 15 /// should just be displayed using the regular JavaScript view instead of a
14 /// custom Dart view. For example, this is used to display the JavaScript view 16 /// custom Dart view. For example, this is used to display the JavaScript view
15 /// of a Dart Function as a child of the regular Function object. 17 /// of a Dart Function as a child of the regular Function object.
16 const skipDartConfig = const Object(); 18 const skipDartConfig = const Object();
17 final int maxIterableChildrenToDisplay = 50; 19 final int maxIterableChildrenToDisplay = 50;
18 20
19 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter()); 21 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter());
20 22
21 String _typeof(object) => JS('String', 'typeof #', object); 23 String _typeof(object) => JS('String', 'typeof #', object);
22 bool _instanceof(object, clazz) => JS('bool', '# instanceof #', object, clazz);
23 24
24 List<String> getOwnPropertyNames(object) => JS('List<String>', 25 List<String> getOwnPropertyNames(object) => JS('List<String>',
25 'dart.list(Object.getOwnPropertyNames(#), #)', object, String); 26 'dart.list(Object.getOwnPropertyNames(#), #)', object, String);
26 27
27 List getOwnPropertySymbols(object) => 28 List getOwnPropertySymbols(object) =>
28 JS('List', 'Object.getOwnPropertySymbols(#)', object); 29 JS('List', 'Object.getOwnPropertySymbols(#)', object);
29 30
30 // TODO(jacobr): move this to dart:js and fully implement. 31 // TODO(jacobr): move this to dart:js and fully implement.
31 class JSNative { 32 class JSNative {
32 // Name may be a String or a Symbol. 33 // Name may be a String or a Symbol.
33 static getProperty(object, name) => JS('', '#[#]', object, name); 34 static getProperty(object, name) => JS('', '#[#]', object, name);
34 // Name may be a String or a Symbol. 35 // Name may be a String or a Symbol.
35 static setProperty(object, name, value) => 36 static setProperty(object, name, value) =>
36 JS('', '#[#]=#', object, name, value); 37 JS('', '#[#]=#', object, name, value);
37 } 38 }
38 39
39 bool isRegularDartObject(object) {
40 if (_typeof(object) == 'function') return false;
41 return _instanceof(object, JS('Type', '#', Object));
42 }
43
44 String getObjectTypeName(object) { 40 String getObjectTypeName(object) {
45 var reifiedType = dart.getReifiedType(object); 41 var reifiedType = dart.getReifiedType(object);
46 if (reifiedType == null) { 42 if (reifiedType == null) {
47 if (_typeof(object) == 'function') { 43 if (_typeof(object) == 'function') {
48 return '[[Raw JavaScript Function]]'; 44 return '[[Raw JavaScript Function]]';
49 } 45 }
50 return '<Error getting type name>'; 46 return '<Error getting type name>';
51 } 47 }
52 return getTypeName(reifiedType); 48 return getTypeName(reifiedType);
53 } 49 }
54 50
55 String getTypeName(Type type) { 51 String getTypeName(Type type) {
56 var name = dart.typeName(type); 52 var name = dart.typeName(type);
57 // Hack to cleanup names for List<dynamic> 53 // Hack to cleanup names for List<dynamic>
58 // TODO(jacobr): it would be nice if there was a way we could distinguish 54 // TODO(jacobr): it would be nice if there was a way we could distinguish
59 // between a List<dynamic> created from Dart and an Array passed in from 55 // between a List<dynamic> created from Dart and an Array passed in from
60 // JavaScript. 56 // JavaScript.
61 if (name == 'JSArray<dynamic>' || 57 if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>')
62 name == 'JSObject<Array>') return 'List<dynamic>'; 58 return 'List<dynamic>';
63 return name; 59 return name;
64 } 60 }
65 61
66 String safePreview(object) { 62 String safePreview(object) {
67 try { 63 try {
68 var preview = _devtoolsFormatter._simpleFormatter.preview(object); 64 var preview = _devtoolsFormatter._simpleFormatter.preview(object);
69 if (preview != null) return preview; 65 if (preview != null) return preview;
70 return object.toString(); 66 return object.toString();
71 } catch (e) { 67 } catch (e) {
72 return '<Exception thrown>'; 68 return '<Exception thrown> $e';
73 } 69 }
74 } 70 }
75 71
76 String symbolName(symbol) { 72 String symbolName(symbol) {
77 var name = symbol.toString(); 73 var name = symbol.toString();
78 assert(name.startsWith('Symbol(')); 74 assert(name.startsWith('Symbol('));
79 return name.substring('Symbol('.length, name.length - 1); 75 return name.substring('Symbol('.length, name.length - 1);
80 } 76 }
81 77
82 bool hasMethod(object, String name) { 78 bool hasMethod(object, String name) {
83 try { 79 try {
84 return dart.hasMethod(object, name); 80 return dart.hasMethod(object, name);
85 } catch (e) { 81 } catch (e) {
86 return false; 82 return false;
87 } 83 }
88 } 84 }
89 85
90 /// [JsonMLFormatter] consumes [NameValuePair] objects and 86 /// [JsonMLFormatter] consumes [NameValuePair] objects and
91 class NameValuePair { 87 class NameValuePair {
92 NameValuePair({this.name, this.value, bool skipDart}) 88 NameValuePair({this.name, this.value, bool skipDart})
93 : skipDart = skipDart == true; 89 : skipDart = skipDart == true;
94 90
91 // Define equality and hashCode so that NameValuePair can be used
92 // in a Set to dedupe entries with duplicate names.
93 operator ==(other) => other is NameValuePair && other.name == name;
94 int get hashCode => name.hashCode;
95
95 final String name; 96 final String name;
96 final Object value; 97 final Object value;
97 final bool skipDart; 98 final bool skipDart;
98 } 99 }
99 100
100 class MapEntry { 101 class MapEntry {
101 MapEntry({this.key, this.value}); 102 MapEntry({this.key, this.value});
102 103
103 final String key; 104 final String key;
104 final Object value; 105 final Object value;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 JSNative.setProperty(_attributes, key, value); 158 JSNative.setProperty(_attributes, key, value);
158 } 159 }
159 160
160 createTextChild(String text) { 161 createTextChild(String text) {
161 _jsonML.add(text); 162 _jsonML.add(text);
162 } 163 }
163 164
164 toJsonML() => _jsonML; 165 toJsonML() => _jsonML;
165 } 166 }
166 167
168 /// Whether an object is a native JavaScript type where we should display the
169 /// JavaScript view of the object instead of the custom Dart specific render
170 /// of properties.
171 bool isNativeJavaScriptObject(object) {
172 var type = _typeof(object);
173 // Treat Node objects as a native JavaScript type as the regular DOM render
174 // in devtools is superior to the dart specific view.
175 return (type != 'object' && type != 'function') ||
176 object is dart.JSObject ||
177 object is html.Node;
178 }
179
167 /// Class implementing the Devtools Formatter API described by: 180 /// Class implementing the Devtools Formatter API described by:
168 /// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335 T3U 181 /// https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335 T3U
169 /// Specifically, a formatter implements a header, hasBody, and body method. 182 /// Specifically, a formatter implements a header, hasBody, and body method.
170 /// This class renders the simple structured format objects [_simpleFormatter] 183 /// This class renders the simple structured format objects [_simpleFormatter]
171 /// provides as JsonML. 184 /// provides as JsonML.
172 class JsonMLFormatter { 185 class JsonMLFormatter {
173 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter 186 // TODO(jacobr): define a SimpleFormatter base class that DartFormatter
174 // implements if we decide to use this class elsewhere. We specify that the 187 // implements if we decide to use this class elsewhere. We specify that the
175 // type is DartFormatter here purely to get type checking benefits not because 188 // type is DartFormatter here purely to get type checking benefits not because
176 // this class is really intended to only support instances of type 189 // this class is really intended to only support instances of type
177 // DartFormatter. 190 // DartFormatter.
178 DartFormatter _simpleFormatter; 191 DartFormatter _simpleFormatter;
179 192
180 JsonMLFormatter(this._simpleFormatter); 193 JsonMLFormatter(this._simpleFormatter);
181 194
182 header(object, config) { 195 header(object, config) {
183 if (identical(config, skipDartConfig)) return null; 196 if (identical(config, skipDartConfig) || isNativeJavaScriptObject(object)) {
197 return null;
198 }
184 199
185 var c = _simpleFormatter.preview(object); 200 var c = _simpleFormatter.preview(object);
186 if (c == null) return null; 201 if (c == null) return null;
187 202
188 // Indicate this is a Dart Object by using a Dart background color. 203 // Indicate this is a Dart Object by using a Dart background color.
189 // This is stylistically a bit ugly but it eases distinguishing Dart and 204 // This is stylistically a bit ugly but it eases distinguishing Dart and
190 // JS objects. 205 // JS objects.
191 var element = new JsonMLElement('span') 206 var element = new JsonMLElement('span')
192 ..setStyle('background-color: #d9edf7') 207 ..setStyle('background-color: #d9edf7')
193 ..createTextChild(c); 208 ..createTextChild(c);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 new MapFormatter(), 265 new MapFormatter(),
251 new IterableFormatter(), 266 new IterableFormatter(),
252 new MapEntryFormatter(), 267 new MapEntryFormatter(),
253 new ClassMetadataFormatter(), 268 new ClassMetadataFormatter(),
254 new HeritageClauseFormatter(), 269 new HeritageClauseFormatter(),
255 new ObjectFormatter() 270 new ObjectFormatter()
256 ]; 271 ];
257 } 272 }
258 273
259 String preview(object) { 274 String preview(object) {
260 if (object == null) return 'null'; 275 try {
261 if (object is num) return object.toString(); 276 if (object == null ||
vsm 2016/05/20 01:30:39 null.toString()? perhaps return "null"?
Jacob 2016/05/20 17:02:36 null.toString is defined as "null" in Dart so we d
262 if (object is String) return '"$object"'; 277 object is num ||
278 object is String ||
279 isNativeJavaScriptObject(object)) {
280 return object.toString();
281 }
263 282
264 for (var formatter in _formatters) { 283 for (var formatter in _formatters) {
265 if (formatter.accept(object)) return formatter.preview(object); 284 if (formatter.accept(object)) return formatter.preview(object);
285 }
286 } catch (e, trace) {
287 // Log formatter internal errors as unfortunately the devtools cannot
288 // be used to debug formatter errors.
289 html.window.console.error("Caught exception $e\n trace:\n$trace");
266 } 290 }
267 291
268 return null; 292 return null;
269 } 293 }
270 294
271 bool hasChildren(object) { 295 bool hasChildren(object) {
272 if (object == null) return false; 296 if (object == null) return false;
273 297 try {
274 for (var formatter in _formatters) { 298 for (var formatter in _formatters) {
275 if (formatter.accept(object)) return formatter.hasChildren(object); 299 if (formatter.accept(object)) return formatter.hasChildren(object);
300 }
301 } catch (e, trace) {
302 // See comment for preview.
303 html.window.console
304 .error("[hasChildren] Caught exception $e\n trace:\n$trace");
276 } 305 }
277
278 return false; 306 return false;
279 } 307 }
280 308
281 List<NameValuePair> children(object) { 309 List<NameValuePair> children(object) {
282 if (object != null) { 310 try {
283 for (var formatter in _formatters) { 311 if (object != null) {
284 if (formatter.accept(object)) return formatter.children(object); 312 for (var formatter in _formatters) {
313 if (formatter.accept(object)) return formatter.children(object);
314 }
285 } 315 }
316 } catch (e, trace) {
317 // See comment for preview.
318 html.window.console.error("Caught exception $e\n trace:\n$trace");
286 } 319 }
287 return <NameValuePair>[]; 320 return <NameValuePair>[];
288 } 321 }
289 } 322 }
290 323
291 /// Default formatter for Dart Objects. 324 /// Default formatter for Dart Objects.
292 class ObjectFormatter extends Formatter { 325 class ObjectFormatter extends Formatter {
293 bool accept(object) => isRegularDartObject(object); 326 bool accept(object) => !isNativeJavaScriptObject(object);
294 327
295 String preview(object) => getObjectTypeName(object); 328 String preview(object) => getObjectTypeName(object);
296 329
297 bool hasChildren(object) => true; 330 bool hasChildren(object) => true;
298 331
299 /// Helper to add members walking up the prototype chain being careful 332 List<NameValuePair> children(object) {
300 /// to avoid properties that are Dart methods. 333 var properties = new LinkedHashSet<NameValuePair>();
301 _addMembers(current, object, List<NameValuePair> properties) { 334 // Set of property names used to avoid duplicates.
302 // TODO(jacobr): optionally distinguish properties and fields so that 335 addMetadataChildren(object, properties);
303 // it is safe to expand untrusted objects without side effects. 336
304 var className = dart.getReifiedType(current).name; 337 /// Helper to add members walking up the prototype chain being careful
305 for (var name in getOwnPropertyNames(current)) { 338 /// to avoid properties that are Dart methods.
306 if (name == 'constructor' || 339 var protoChain = <Object>[];
307 name == '__proto__' || 340 var current = object;
308 name == className) continue; 341 while (current != null &&
309 if (hasMethod(object, name)) { 342 !isNativeJavaScriptObject(current) &&
310 continue; 343 JS("bool", "# !== Object.prototype", current)) {
344 protoChain.add(current);
345 current = JSNative.getProperty(current, '__proto__');
346 }
347
348 // We walk the prototype chain for symbol properties
349 // because they take priority and are accessed instead of
350 // Dart properties according to Dart calling conventions.
vsm 2016/05/20 01:30:39 We have some of this metadata encoded on the type
Jacob 2016/05/20 17:02:36 Agreed that would be much better. Adding a TODO. P
351 for (current in protoChain) {
352 for (var symbol in getOwnPropertySymbols(current)) {
353 var dartName = symbolName(symbol);
354 if (hasMethod(object, dartName)) {
355 continue;
356 }
357 // TODO(jacobr): find a cleaner solution than checking for dartx
358 String dartXPrefix = 'dartx.';
359 if (dartName.startsWith(dartXPrefix)) {
360 dartName = dartName.substring(dartXPrefix.length);
361 } else if (!dartName.startsWith('_')) {
362 // Dart method extension names should either be from dartx or should
363 // start with an _
364 continue;
365 }
366 var value;
367 try {
368 value = JSNative.getProperty(object, symbol);
369 } catch (e) {
370 value = '<Exception thrown> $e';
371 }
372 properties.add(new NameValuePair(name: dartName, value: value));
311 } 373 }
312 var value; 374 }
313 try { 375
314 value = JSNative.getProperty(object, name); 376 for (current in protoChain) {
315 } catch (e) { 377 // TODO(jacobr): optionally distinguish properties and fields so that
316 value = '<Exception thrown>'; 378 // it is safe to expand untrusted objects without side effects.
379 var className = dart.getReifiedType(current).name;
380 for (var name in getOwnPropertyNames(current)) {
381 if (customNames.contains(name) || name == className) continue;
vsm 2016/05/20 01:30:39 You're getting an SDK error on this. :-)
Jacob 2016/05/20 17:02:36 Wow. Fixed.
382 if (hasMethod(object, name)) {
383 continue;
384 }
385 var value;
386 try {
387 value = JSNative.getProperty(object, name);
388 } catch (e) {
389 value = '<Exception thrown> $e';
390 }
391 properties.add(new NameValuePair(name: name, value: value));
317 } 392 }
318 properties.add(new NameValuePair(name: name, value: value));
319 } 393 }
320 for (var symbol in getOwnPropertySymbols(current)) { 394
321 var dartName = symbolName(symbol); 395 return properties.toList();
322 if (hasMethod(object, dartName)) {
323 continue;
324 }
325 var value;
326 try {
327 value = JSNative.getProperty(object, symbol);
328 } catch (e) {
329 value = '<Exception thrown>';
330 }
331 properties.add(new NameValuePair(name: dartName, value: value));
332 }
333 var base = JSNative.getProperty(current, '__proto__');
334 if (base == null) return;
335 if (isRegularDartObject(base)) {
336 _addMembers(base, object, properties);
337 }
338 } 396 }
339 397
340 List<NameValuePair> children(object) { 398 addMetadataChildren(object, Set<NameValuePair> ret) {
341 var properties = <NameValuePair>[];
342 addMetadataChildren(object, properties);
343 _addMembers(object, object, properties);
344 return properties;
345 }
346
347 addMetadataChildren(object, List<NameValuePair> ret) {
348 ret.add( 399 ret.add(
349 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object))); 400 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object)));
350 } 401 }
351 } 402 }
352 403
353 /// Formatter for Dart Function objects. 404 /// Formatter for Dart Function objects.
354 /// Dart functions happen to be regular JavaScript Function objects but 405 /// Dart functions happen to be regular JavaScript Function objects but
355 /// we can distinguish them based on whether they have been tagged with 406 /// we can distinguish them based on whether they have been tagged with
356 /// runtime type information. 407 /// runtime type information.
357 class FunctionFormatter extends Formatter { 408 class FunctionFormatter extends Formatter {
(...skipping 24 matching lines...) Expand all
382 String preview(object) { 433 String preview(object) {
383 Map map = object; 434 Map map = object;
384 return '${getObjectTypeName(map)} length ${map.length}'; 435 return '${getObjectTypeName(map)} length ${map.length}';
385 } 436 }
386 437
387 List<NameValuePair> children(object) { 438 List<NameValuePair> children(object) {
388 // TODO(jacobr): be lazier about enumerating contents of Maps that are not 439 // TODO(jacobr): be lazier about enumerating contents of Maps that are not
389 // the build in LinkedHashMap class. 440 // the build in LinkedHashMap class.
390 // TODO(jacobr): handle large Maps better. 441 // TODO(jacobr): handle large Maps better.
391 Map map = object; 442 Map map = object;
392 var keys = map.keys.toList(); 443 var entries = new LinkedHashSet<NameValuePair>();
393 var entries = <NameValuePair>[];
394 map.forEach((key, value) { 444 map.forEach((key, value) {
395 var entryWrapper = new MapEntry(key: key, value: value); 445 var entryWrapper = new MapEntry(key: key, value: value);
396 entries.add(new NameValuePair( 446 entries.add(new NameValuePair(
397 name: entries.length.toString(), value: entryWrapper)); 447 name: entries.length.toString(), value: entryWrapper));
398 }); 448 });
399 addMetadataChildren(object, entries); 449 addMetadataChildren(object, entries);
400 return entries; 450 return entries.toList();
401 } 451 }
402 } 452 }
403 453
404 /// Formatter for Dart Iterable objects including List and Set. 454 /// Formatter for Dart Iterable objects including List and Set.
405 class IterableFormatter extends ObjectFormatter { 455 class IterableFormatter extends ObjectFormatter {
406 bool accept(object) => object is Iterable; 456 bool accept(object) => object is Iterable;
407 457
408 String preview(object) { 458 String preview(object) {
409 Iterable iterable = object; 459 Iterable iterable = object;
410 try { 460 try {
411 var length = iterable.length; 461 var length = iterable.length;
412 return '${getObjectTypeName(iterable)} length $length'; 462 return '${getObjectTypeName(iterable)} length $length';
413 } catch (_) { 463 } catch (_) {
414 return '${getObjectTypeName(iterable)}'; 464 return '${getObjectTypeName(iterable)}';
415 } 465 }
416 } 466 }
417 467
418 bool hasChildren(object) => true; 468 bool hasChildren(object) => true;
419 469
420 List<NameValuePair> children(object) { 470 List<NameValuePair> children(object) {
421 // TODO(jacobr): be lazier about enumerating contents of Iterables that 471 // TODO(jacobr): be lazier about enumerating contents of Iterables that
422 // are not the built in Set or List types. 472 // are not the built in Set or List types.
423 // TODO(jacobr): handle large Iterables better. 473 // TODO(jacobr): handle large Iterables better.
424 // TODO(jacobr): consider only using numeric indices 474 // TODO(jacobr): consider only using numeric indices
425 Iterable iterable = object; 475 Iterable iterable = object;
426 var ret = <NameValuePair>[]; 476 var ret = new LinkedHashSet<NameValuePair>();
427 var i = 0; 477 var i = 0;
428 for (var entry in iterable) { 478 for (var entry in iterable) {
429 if (i > maxIterableChildrenToDisplay) { 479 if (i > maxIterableChildrenToDisplay) {
430 ret.add(new NameValuePair( 480 ret.add(new NameValuePair(
431 name: 'Warning', value: 'Truncated Iterable display')); 481 name: 'Warning', value: 'Truncated Iterable display'));
432 // TODO(jacobr): provide an expandable entry to show more entries. 482 // TODO(jacobr): provide an expandable entry to show more entries.
433 break; 483 break;
434 } 484 }
435 ret.add(new NameValuePair(name: i.toString(), value: entry)); 485 ret.add(new NameValuePair(name: i.toString(), value: entry));
436 i++; 486 i++;
437 } 487 }
438 // TODO(jacobr): provide a link to show regular class properties here. 488 // TODO(jacobr): provide a link to show regular class properties here.
439 // required for subclasses of iterable, etc. 489 // required for subclasses of iterable, etc.
440 addMetadataChildren(object, ret); 490 addMetadataChildren(object, ret);
441 return ret; 491 return ret.toList();
442 } 492 }
443 } 493 }
444 494
445 // This class does double duting displaying metadata for 495 // This class does double duting displaying metadata for
446 class ClassMetadataFormatter implements Formatter { 496 class ClassMetadataFormatter implements Formatter {
447 accept(object) => object is ClassMetadata; 497 accept(object) => object is ClassMetadata;
448 498
449 _getType(object) { 499 _getType(object) {
450 if (object is Type) return object; 500 if (object is Type) return object;
451 return dart.getReifiedType(object); 501 return dart.getReifiedType(object);
(...skipping 12 matching lines...) Expand all
464 // links to the superclass, mixins, implemented interfaces, and methods. 514 // links to the superclass, mixins, implemented interfaces, and methods.
465 var type = _getType(entry.object); 515 var type = _getType(entry.object);
466 var ret = <NameValuePair>[]; 516 var ret = <NameValuePair>[];
467 var implements = dart.getImplements(type); 517 var implements = dart.getImplements(type);
468 if (implements != null) { 518 if (implements != null) {
469 ret.add(new NameValuePair( 519 ret.add(new NameValuePair(
470 name: '[[Implements]]', 520 name: '[[Implements]]',
471 value: new HeritageClause('implements', implements()))); 521 value: new HeritageClause('implements', implements())));
472 } 522 }
473 var mixins = dart.getMixins(type); 523 var mixins = dart.getMixins(type);
474 if (mixins != null) { 524 if (mixins != null && mixins.isNotEmpty) {
475 ret.add(new NameValuePair( 525 ret.add(new NameValuePair(
476 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins()))); 526 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
477 } 527 }
478 ret.add(new NameValuePair( 528 ret.add(new NameValuePair(
479 name: '[[JavaScript View]]', value: entry.object, skipDart: true)); 529 name: '[[JavaScript View]]', value: entry.object, skipDart: true));
480 530
481 // TODO(jacobr): provide a link to the base class or perhaps the entire 531 // TODO(jacobr): provide a link to the base class or perhaps the entire
482 // base class hierarchy as a flat list. 532 // base class hierarchy as a flat list.
483 533
484 if (entry.object is! Type) { 534 if (entry.object is! Type) {
485 ret.add(new NameValuePair( 535 ret.add(new NameValuePair(
486 name: '[[JavaScript Constructor]]', 536 name: '[[JavaScript Constructor]]',
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 return ret; 581 return ret;
532 } 582 }
533 } 583 }
534 584
535 /// This entry point is automatically invoked by the code generated by 585 /// This entry point is automatically invoked by the code generated by
536 /// Dart Dev Compiler 586 /// Dart Dev Compiler
537 registerDevtoolsFormatter() { 587 registerDevtoolsFormatter() {
538 var formatters = [_devtoolsFormatter]; 588 var formatters = [_devtoolsFormatter];
539 JS('', 'dart.global.devtoolsFormatters = #', formatters); 589 JS('', 'dart.global.devtoolsFormatters = #', formatters);
540 } 590 }
OLDNEW
« no previous file with comments | « tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | tool/sdk_expected_errors.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698