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

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: ptal 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;
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 ||
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 static Set<String> _customNames = new Set()
327 ..add('constructor')
328 ..add('prototype')
329 ..add('__proto__');
330 bool accept(object) => !isNativeJavaScriptObject(object);
294 331
295 String preview(object) => getObjectTypeName(object); 332 String preview(object) => getObjectTypeName(object);
296 333
297 bool hasChildren(object) => true; 334 bool hasChildren(object) => true;
298 335
299 /// Helper to add members walking up the prototype chain being careful 336 List<NameValuePair> children(object) {
300 /// to avoid properties that are Dart methods. 337 var properties = new LinkedHashSet<NameValuePair>();
301 _addMembers(current, object, List<NameValuePair> properties) { 338 // Set of property names used to avoid duplicates.
302 // TODO(jacobr): optionally distinguish properties and fields so that 339 addMetadataChildren(object, properties);
303 // it is safe to expand untrusted objects without side effects. 340
304 var className = dart.getReifiedType(current).name; 341 /// Helper to add members walking up the prototype chain being careful
305 for (var name in getOwnPropertyNames(current)) { 342 /// to avoid properties that are Dart methods.
306 if (name == 'constructor' || 343 var protoChain = <Object>[];
307 name == '__proto__' || 344 var current = object;
308 name == className) continue; 345 while (current != null &&
309 if (hasMethod(object, name)) { 346 !isNativeJavaScriptObject(current) &&
310 continue; 347 JS("bool", "# !== Object.prototype", current)) {
348 protoChain.add(current);
349 current = JSNative.getProperty(current, '__proto__');
350 }
351
352 // We walk the prototype chain for symbol properties because they take
353 // priority and are accessed instead of Dart properties according to Dart
354 // calling conventions.
355 // TODO(jacobr): where possible use the data stored by dart.setSignature
356 // instead of walking the JavaScript object directly.
357 for (current in protoChain) {
358 for (var symbol in getOwnPropertySymbols(current)) {
359 var dartName = symbolName(symbol);
360 if (hasMethod(object, dartName)) {
361 continue;
362 }
363 // TODO(jacobr): find a cleaner solution than checking for dartx
364 String dartXPrefix = 'dartx.';
365 if (dartName.startsWith(dartXPrefix)) {
366 dartName = dartName.substring(dartXPrefix.length);
367 } else if (!dartName.startsWith('_')) {
368 // Dart method extension names should either be from dartx or should
369 // start with an _
370 continue;
371 }
372 var value;
373 try {
374 value = JSNative.getProperty(object, symbol);
375 } catch (e) {
376 value = '<Exception thrown> $e';
377 }
378 properties.add(new NameValuePair(name: dartName, value: value));
311 } 379 }
312 var value; 380 }
313 try { 381
314 value = JSNative.getProperty(object, name); 382 for (current in protoChain) {
315 } catch (e) { 383 // TODO(jacobr): optionally distinguish properties and fields so that
316 value = '<Exception thrown>'; 384 // it is safe to expand untrusted objects without side effects.
385 var className = dart.getReifiedType(current).name;
386 for (var name in getOwnPropertyNames(current)) {
387 if (_customNames.contains(name) || name == className) continue;
388 if (hasMethod(object, name)) {
389 continue;
390 }
391 var value;
392 try {
393 value = JSNative.getProperty(object, name);
394 } catch (e) {
395 value = '<Exception thrown> $e';
396 }
397 properties.add(new NameValuePair(name: name, value: value));
317 } 398 }
318 properties.add(new NameValuePair(name: name, value: value));
319 } 399 }
320 for (var symbol in getOwnPropertySymbols(current)) { 400
321 var dartName = symbolName(symbol); 401 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 } 402 }
339 403
340 List<NameValuePair> children(object) { 404 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( 405 ret.add(
349 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object))); 406 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object)));
350 } 407 }
351 } 408 }
352 409
353 /// Formatter for Dart Function objects. 410 /// Formatter for Dart Function objects.
354 /// Dart functions happen to be regular JavaScript Function objects but 411 /// Dart functions happen to be regular JavaScript Function objects but
355 /// we can distinguish them based on whether they have been tagged with 412 /// we can distinguish them based on whether they have been tagged with
356 /// runtime type information. 413 /// runtime type information.
357 class FunctionFormatter extends Formatter { 414 class FunctionFormatter extends Formatter {
(...skipping 24 matching lines...) Expand all
382 String preview(object) { 439 String preview(object) {
383 Map map = object; 440 Map map = object;
384 return '${getObjectTypeName(map)} length ${map.length}'; 441 return '${getObjectTypeName(map)} length ${map.length}';
385 } 442 }
386 443
387 List<NameValuePair> children(object) { 444 List<NameValuePair> children(object) {
388 // TODO(jacobr): be lazier about enumerating contents of Maps that are not 445 // TODO(jacobr): be lazier about enumerating contents of Maps that are not
389 // the build in LinkedHashMap class. 446 // the build in LinkedHashMap class.
390 // TODO(jacobr): handle large Maps better. 447 // TODO(jacobr): handle large Maps better.
391 Map map = object; 448 Map map = object;
392 var keys = map.keys.toList(); 449 var entries = new LinkedHashSet<NameValuePair>();
393 var entries = <NameValuePair>[];
394 map.forEach((key, value) { 450 map.forEach((key, value) {
395 var entryWrapper = new MapEntry(key: key, value: value); 451 var entryWrapper = new MapEntry(key: key, value: value);
396 entries.add(new NameValuePair( 452 entries.add(new NameValuePair(
397 name: entries.length.toString(), value: entryWrapper)); 453 name: entries.length.toString(), value: entryWrapper));
398 }); 454 });
399 addMetadataChildren(object, entries); 455 addMetadataChildren(object, entries);
400 return entries; 456 return entries.toList();
401 } 457 }
402 } 458 }
403 459
404 /// Formatter for Dart Iterable objects including List and Set. 460 /// Formatter for Dart Iterable objects including List and Set.
405 class IterableFormatter extends ObjectFormatter { 461 class IterableFormatter extends ObjectFormatter {
406 bool accept(object) => object is Iterable; 462 bool accept(object) => object is Iterable;
407 463
408 String preview(object) { 464 String preview(object) {
409 Iterable iterable = object; 465 Iterable iterable = object;
410 try { 466 try {
411 var length = iterable.length; 467 var length = iterable.length;
412 return '${getObjectTypeName(iterable)} length $length'; 468 return '${getObjectTypeName(iterable)} length $length';
413 } catch (_) { 469 } catch (_) {
414 return '${getObjectTypeName(iterable)}'; 470 return '${getObjectTypeName(iterable)}';
415 } 471 }
416 } 472 }
417 473
418 bool hasChildren(object) => true; 474 bool hasChildren(object) => true;
419 475
420 List<NameValuePair> children(object) { 476 List<NameValuePair> children(object) {
421 // TODO(jacobr): be lazier about enumerating contents of Iterables that 477 // TODO(jacobr): be lazier about enumerating contents of Iterables that
422 // are not the built in Set or List types. 478 // are not the built in Set or List types.
423 // TODO(jacobr): handle large Iterables better. 479 // TODO(jacobr): handle large Iterables better.
424 // TODO(jacobr): consider only using numeric indices 480 // TODO(jacobr): consider only using numeric indices
425 Iterable iterable = object; 481 Iterable iterable = object;
426 var ret = <NameValuePair>[]; 482 var ret = new LinkedHashSet<NameValuePair>();
427 var i = 0; 483 var i = 0;
428 for (var entry in iterable) { 484 for (var entry in iterable) {
429 if (i > maxIterableChildrenToDisplay) { 485 if (i > maxIterableChildrenToDisplay) {
430 ret.add(new NameValuePair( 486 ret.add(new NameValuePair(
431 name: 'Warning', value: 'Truncated Iterable display')); 487 name: 'Warning', value: 'Truncated Iterable display'));
432 // TODO(jacobr): provide an expandable entry to show more entries. 488 // TODO(jacobr): provide an expandable entry to show more entries.
433 break; 489 break;
434 } 490 }
435 ret.add(new NameValuePair(name: i.toString(), value: entry)); 491 ret.add(new NameValuePair(name: i.toString(), value: entry));
436 i++; 492 i++;
437 } 493 }
438 // TODO(jacobr): provide a link to show regular class properties here. 494 // TODO(jacobr): provide a link to show regular class properties here.
439 // required for subclasses of iterable, etc. 495 // required for subclasses of iterable, etc.
440 addMetadataChildren(object, ret); 496 addMetadataChildren(object, ret);
441 return ret; 497 return ret.toList();
442 } 498 }
443 } 499 }
444 500
445 // This class does double duting displaying metadata for 501 // This class does double duting displaying metadata for
446 class ClassMetadataFormatter implements Formatter { 502 class ClassMetadataFormatter implements Formatter {
447 accept(object) => object is ClassMetadata; 503 accept(object) => object is ClassMetadata;
448 504
449 _getType(object) { 505 _getType(object) {
450 if (object is Type) return object; 506 if (object is Type) return object;
451 return dart.getReifiedType(object); 507 return dart.getReifiedType(object);
(...skipping 12 matching lines...) Expand all
464 // links to the superclass, mixins, implemented interfaces, and methods. 520 // links to the superclass, mixins, implemented interfaces, and methods.
465 var type = _getType(entry.object); 521 var type = _getType(entry.object);
466 var ret = <NameValuePair>[]; 522 var ret = <NameValuePair>[];
467 var implements = dart.getImplements(type); 523 var implements = dart.getImplements(type);
468 if (implements != null) { 524 if (implements != null) {
469 ret.add(new NameValuePair( 525 ret.add(new NameValuePair(
470 name: '[[Implements]]', 526 name: '[[Implements]]',
471 value: new HeritageClause('implements', implements()))); 527 value: new HeritageClause('implements', implements())));
472 } 528 }
473 var mixins = dart.getMixins(type); 529 var mixins = dart.getMixins(type);
474 if (mixins != null) { 530 if (mixins != null && mixins.isNotEmpty) {
475 ret.add(new NameValuePair( 531 ret.add(new NameValuePair(
476 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins()))); 532 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
477 } 533 }
478 ret.add(new NameValuePair( 534 ret.add(new NameValuePair(
479 name: '[[JavaScript View]]', value: entry.object, skipDart: true)); 535 name: '[[JavaScript View]]', value: entry.object, skipDart: true));
480 536
481 // TODO(jacobr): provide a link to the base class or perhaps the entire 537 // TODO(jacobr): provide a link to the base class or perhaps the entire
482 // base class hierarchy as a flat list. 538 // base class hierarchy as a flat list.
483 539
484 if (entry.object is! Type) { 540 if (entry.object is! Type) {
485 ret.add(new NameValuePair( 541 ret.add(new NameValuePair(
486 name: '[[JavaScript Constructor]]', 542 name: '[[JavaScript Constructor]]',
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 return ret; 587 return ret;
532 } 588 }
533 } 589 }
534 590
535 /// This entry point is automatically invoked by the code generated by 591 /// This entry point is automatically invoked by the code generated by
536 /// Dart Dev Compiler 592 /// Dart Dev Compiler
537 registerDevtoolsFormatter() { 593 registerDevtoolsFormatter() {
538 var formatters = [_devtoolsFormatter]; 594 var formatters = [_devtoolsFormatter];
539 JS('', 'dart.global.devtoolsFormatters = #', formatters); 595 JS('', 'dart.global.devtoolsFormatters = #', formatters);
540 } 596 }
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