Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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._js_mirrors; | 5 library dart._js_mirrors; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection' show UnmodifiableListView; | |
| 8 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 9 | 10 |
| 10 import 'dart:_foreign_helper' show | 11 import 'dart:_foreign_helper' show |
| 11 JS, | 12 JS, |
| 12 JS_CURRENT_ISOLATE, | 13 JS_CURRENT_ISOLATE, |
| 13 JS_CURRENT_ISOLATE_CONTEXT, | 14 JS_CURRENT_ISOLATE_CONTEXT, |
| 14 JS_GET_NAME; | 15 JS_GET_NAME; |
| 15 import 'dart:_collection-dev' as _symbol_dev; | 16 import 'dart:_collection-dev' as _symbol_dev; |
| 16 import 'dart:_js_helper' show | 17 import 'dart:_js_helper' show |
| 17 BoundClosure, | 18 BoundClosure, |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 33 /// No-op method that is called to inform the compiler that metadata must be | 34 /// No-op method that is called to inform the compiler that metadata must be |
| 34 /// preserved at runtime. | 35 /// preserved at runtime. |
| 35 preserveMetadata() {} | 36 preserveMetadata() {} |
| 36 | 37 |
| 37 String getName(Symbol symbol) { | 38 String getName(Symbol symbol) { |
| 38 preserveNames(); | 39 preserveNames(); |
| 39 return n(symbol); | 40 return n(symbol); |
| 40 } | 41 } |
| 41 | 42 |
| 42 class JsMirrorSystem implements MirrorSystem { | 43 class JsMirrorSystem implements MirrorSystem { |
| 44 UnmodifiableMapView<Uri, LibraryMirror> _cachedLibraries; | |
| 45 | |
| 43 final IsolateMirror isolate = new JsIsolateMirror(); | 46 final IsolateMirror isolate = new JsIsolateMirror(); |
| 44 | 47 |
| 45 TypeMirror get dynamicType => _dynamicType; | 48 TypeMirror get dynamicType => _dynamicType; |
| 46 TypeMirror get voidType => _voidType; | 49 TypeMirror get voidType => _voidType; |
| 47 | 50 |
| 48 final static TypeMirror _dynamicType = | 51 final static TypeMirror _dynamicType = |
| 49 new JsTypeMirror(const Symbol('dynamic')); | 52 new JsTypeMirror(const Symbol('dynamic')); |
| 50 final static TypeMirror _voidType = new JsTypeMirror(const Symbol('void')); | 53 final static TypeMirror _voidType = new JsTypeMirror(const Symbol('void')); |
| 51 | 54 |
| 52 static final Map<String, List<LibraryMirror>> librariesByName = | 55 static final Map<String, List<LibraryMirror>> librariesByName = |
| 53 computeLibrariesByName(); | 56 computeLibrariesByName(); |
| 54 | 57 |
| 55 Map<Uri, LibraryMirror> get libraries { | 58 Map<Uri, LibraryMirror> get libraries { |
| 56 Map<Uri, LibraryMirror> result = new Map<Uri, LibraryMirror>(); | 59 if (_cachedLibraries != null) return _cachedLibraries; |
| 60 Map<Uri, LibraryMirror> result = new Map(); | |
| 57 for (List<LibraryMirror> list in librariesByName.values) { | 61 for (List<LibraryMirror> list in librariesByName.values) { |
| 58 for (LibraryMirror library in list) { | 62 for (LibraryMirror library in list) { |
| 59 result[library.uri] = library; | 63 result[library.uri] = library; |
| 60 } | 64 } |
| 61 } | 65 } |
| 62 return result; | 66 return _cachedLibraries = |
| 67 new UnmodifiableMapView<Uri, LibraryMirror>(result); | |
| 63 } | 68 } |
| 64 | 69 |
| 65 Iterable<LibraryMirror> findLibrary(Symbol libraryName) { | 70 Iterable<LibraryMirror> findLibrary(Symbol libraryName) { |
| 66 return new List<LibraryMirror>.from(librariesByName[n(libraryName)]); | 71 return new UnmodifiableListView<LibraryMirror>( |
| 72 librariesByName[n(libraryName)]); | |
| 67 } | 73 } |
| 68 | 74 |
| 69 static Map<String, List<LibraryMirror>> computeLibrariesByName() { | 75 static Map<String, List<LibraryMirror>> computeLibrariesByName() { |
| 70 disableTreeShaking(); | 76 disableTreeShaking(); |
| 71 var result = new Map<String, List<LibraryMirror>>(); | 77 var result = new Map<String, List<LibraryMirror>>(); |
| 72 var jsLibraries = JS('JSExtendableArray|Null', 'init.libraries'); | 78 var jsLibraries = JS('JSExtendableArray|Null', 'init.libraries'); |
| 73 if (jsLibraries == null) return result; | 79 if (jsLibraries == null) return result; |
| 74 for (List data in jsLibraries) { | 80 for (List data in jsLibraries) { |
| 75 String name = data[0]; | 81 String name = data[0]; |
| 76 Uri uri = Uri.parse(data[1]); | 82 Uri uri = Uri.parse(data[1]); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror | 187 class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror |
| 182 implements LibraryMirror { | 188 implements LibraryMirror { |
| 183 final Uri uri; | 189 final Uri uri; |
| 184 final List<String> _classes; | 190 final List<String> _classes; |
| 185 final List<String> _functions; | 191 final List<String> _functions; |
| 186 final List _metadata; | 192 final List _metadata; |
| 187 final String _compactFieldSpecification; | 193 final String _compactFieldSpecification; |
| 188 final bool _isRoot; | 194 final bool _isRoot; |
| 189 List<JsMethodMirror> _cachedFunctionMirrors; | 195 List<JsMethodMirror> _cachedFunctionMirrors; |
| 190 List<JsVariableMirror> _cachedFields; | 196 List<JsVariableMirror> _cachedFields; |
| 197 UnmodifiableMapView<Symbol, ClassMirror> _cachedClasses; | |
| 198 UnmodifiableMapView<Symbol, MethodMirror> _cachedFunctions; | |
| 199 UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters; | |
| 200 UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters; | |
| 201 UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables; | |
| 202 UnmodifiableMapView<Symbol, Mirror> _cachedMembers; | |
| 203 UnmodifiableListView<InstanceMirror> _cachedMetadata; | |
| 191 | 204 |
| 192 JsLibraryMirror(Symbol simpleName, | 205 JsLibraryMirror(Symbol simpleName, |
| 193 this.uri, | 206 this.uri, |
| 194 this._classes, | 207 this._classes, |
| 195 this._functions, | 208 this._functions, |
| 196 this._metadata, | 209 this._metadata, |
| 197 this._compactFieldSpecification, | 210 this._compactFieldSpecification, |
| 198 this._isRoot) | 211 this._isRoot) |
| 199 : super(simpleName); | 212 : super(simpleName); |
| 200 | 213 |
| 201 String get _prettyName => 'LibraryMirror'; | 214 String get _prettyName => 'LibraryMirror'; |
| 202 | 215 |
| 203 Symbol get qualifiedName => simpleName; | 216 Symbol get qualifiedName => simpleName; |
| 204 | 217 |
| 205 List<JsMethodMirror> get _methods => _functionMirrors; | 218 List<JsMethodMirror> get _methods => _functionMirrors; |
| 206 | 219 |
| 207 Map<Symbol, ClassMirror> get classes { | 220 Map<Symbol, ClassMirror> get classes { |
| 208 var result = new Map<Symbol, ClassMirror>(); | 221 if (_cachedClasses != null) return _cachedClasses; |
| 222 var result = new Map(); | |
| 209 for (String className in _classes) { | 223 for (String className in _classes) { |
| 210 JsClassMirror cls = reflectClassByMangledName(className); | 224 JsClassMirror cls = reflectClassByMangledName(className); |
| 211 result[cls.simpleName] = cls; | 225 result[cls.simpleName] = cls; |
| 212 cls._owner = this; | 226 cls._owner = this; |
| 213 } | 227 } |
| 214 return result; | 228 return _cachedClasses = |
| 229 new UnmodifiableMapView<Symbol, ClassMirror>(result); | |
| 215 } | 230 } |
| 216 | 231 |
| 217 InstanceMirror setField(Symbol fieldName, Object arg) { | 232 InstanceMirror setField(Symbol fieldName, Object arg) { |
| 218 String name = n(fieldName); | 233 String name = n(fieldName); |
| 219 if (name.endsWith('=')) throw new ArgumentError(''); | 234 if (name.endsWith('=')) throw new ArgumentError(''); |
| 220 var mirror = functions[s('$name=')]; | 235 var mirror = functions[s('$name=')]; |
| 221 if (mirror == null) mirror = variables[fieldName]; | 236 if (mirror == null) mirror = variables[fieldName]; |
| 222 if (mirror == null) { | 237 if (mirror == null) { |
| 223 // TODO(ahe): What receiver to use? | 238 // TODO(ahe): What receiver to use? |
| 224 throw new NoSuchMethodError(this, '${n(fieldName)}=', [arg], null); | 239 throw new NoSuchMethodError(this, '${n(fieldName)}=', [arg], null); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 mirror._owner = this; | 301 mirror._owner = this; |
| 287 } | 302 } |
| 288 return _cachedFunctionMirrors = result; | 303 return _cachedFunctionMirrors = result; |
| 289 } | 304 } |
| 290 | 305 |
| 291 List<VariableMirror> get _fields { | 306 List<VariableMirror> get _fields { |
| 292 if (_cachedFields != null) return _cachedFields; | 307 if (_cachedFields != null) return _cachedFields; |
| 293 var result = <VariableMirror>[]; | 308 var result = <VariableMirror>[]; |
| 294 parseCompactFieldSpecification( | 309 parseCompactFieldSpecification( |
| 295 this, _compactFieldSpecification, true, result); | 310 this, _compactFieldSpecification, true, result); |
| 296 _cachedFields = result; | 311 return _cachedFields = result; |
| 297 return _cachedFields; | |
| 298 } | 312 } |
| 299 | 313 |
| 300 Map<Symbol, MethodMirror> get functions { | 314 Map<Symbol, MethodMirror> get functions { |
| 301 var result = new Map<Symbol, MethodMirror>(); | 315 if (_cachedFunctions != null) return _cachedFunctions; |
| 316 var result = new Map(); | |
| 302 for (JsMethodMirror mirror in _functionMirrors) { | 317 for (JsMethodMirror mirror in _functionMirrors) { |
| 303 if (!mirror.isConstructor) result[mirror.simpleName] = mirror; | 318 if (!mirror.isConstructor) result[mirror.simpleName] = mirror; |
| 304 } | 319 } |
| 305 return result; | 320 return _cachedFunctions = |
| 321 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 306 } | 322 } |
| 307 | 323 |
| 308 Map<Symbol, MethodMirror> get getters { | 324 Map<Symbol, MethodMirror> get getters { |
| 309 var result = new Map<Symbol, MethodMirror>(); | 325 if (_cachedGetters != null) return _cachedGetters; |
| 326 var result = new Map(); | |
| 310 // TODO(ahe): Implement this. | 327 // TODO(ahe): Implement this. |
| 311 return result; | 328 return _cachedGetters = |
| 329 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 312 } | 330 } |
| 313 | 331 |
| 314 Map<Symbol, MethodMirror> get setters { | 332 Map<Symbol, MethodMirror> get setters { |
| 315 var result = new Map<Symbol, MethodMirror>(); | 333 if (_cachedSetters != null) return _cachedSetters; |
| 334 var result = new Map(); | |
| 316 // TODO(ahe): Implement this. | 335 // TODO(ahe): Implement this. |
| 317 return result; | 336 return _cachedSetters = |
| 337 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 318 } | 338 } |
| 319 | 339 |
| 320 Map<Symbol, VariableMirror> get variables { | 340 Map<Symbol, VariableMirror> get variables { |
| 321 var result = new Map<Symbol, VariableMirror>(); | 341 if (_cachedVariables != null) return _cachedVariables; |
| 342 var result = new Map(); | |
| 322 for (JsVariableMirror mirror in _fields) { | 343 for (JsVariableMirror mirror in _fields) { |
| 323 result[mirror.simpleName] = mirror; | 344 result[mirror.simpleName] = mirror; |
| 324 } | 345 } |
| 325 return result; | 346 return _cachedVariables = |
| 347 new UnmodifiableMapView<Symbol, VariableMirror>(result); | |
| 326 } | 348 } |
| 327 | 349 |
| 328 Map<Symbol, Mirror> get members { | 350 Map<Symbol, Mirror> get members { |
| 329 Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(classes); | 351 if (_cachedMembers != null) return _cachedMembers; |
| 352 Map<Symbol, Mirror> result = new Map.from(classes); | |
| 330 addToResult(Symbol key, Mirror value) { | 353 addToResult(Symbol key, Mirror value) { |
| 331 result[key] = value; | 354 result[key] = value; |
| 332 } | 355 } |
| 333 functions.forEach(addToResult); | 356 functions.forEach(addToResult); |
| 334 getters.forEach(addToResult); | 357 getters.forEach(addToResult); |
| 335 setters.forEach(addToResult); | 358 setters.forEach(addToResult); |
| 336 variables.forEach(addToResult); | 359 variables.forEach(addToResult); |
| 337 return result; | 360 return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result); |
| 338 } | 361 } |
| 339 | 362 |
| 340 List<InstanceMirror> get metadata { | 363 List<InstanceMirror> get metadata { |
| 364 if (_cachedMetadata != null) return _cachedMetadata; | |
| 341 preserveMetadata(); | 365 preserveMetadata(); |
| 342 return _metadata.map(reflect).toList(); | 366 return _cachedMetadata = |
| 367 new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect)); | |
| 343 } | 368 } |
| 344 | 369 |
| 345 // TODO(ahe): Test this getter. | 370 // TODO(ahe): Test this getter. |
| 346 DeclarationMirror get owner => null; | 371 DeclarationMirror get owner => null; |
| 347 } | 372 } |
| 348 | 373 |
| 349 String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); | 374 String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); |
| 350 | 375 |
| 351 Symbol s(String name) { | 376 Symbol s(String name) { |
| 352 if (name == null) return null; | 377 if (name == null) return null; |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 class JsClassMirror extends JsTypeMirror with JsObjectMirror | 529 class JsClassMirror extends JsTypeMirror with JsObjectMirror |
| 505 implements ClassMirror { | 530 implements ClassMirror { |
| 506 final String _mangledName; | 531 final String _mangledName; |
| 507 final _jsConstructorOrInterceptor; | 532 final _jsConstructorOrInterceptor; |
| 508 final String _fieldsDescriptor; | 533 final String _fieldsDescriptor; |
| 509 final List _fieldsMetadata; | 534 final List _fieldsMetadata; |
| 510 List _metadata; | 535 List _metadata; |
| 511 JsClassMirror _superclass; | 536 JsClassMirror _superclass; |
| 512 List<JsMethodMirror> _cachedMethods; | 537 List<JsMethodMirror> _cachedMethods; |
| 513 List<JsVariableMirror> _cachedFields; | 538 List<JsVariableMirror> _cachedFields; |
| 539 UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors; | |
| 540 UnmodifiableMapView<Symbol, MethodMirror> _cachedMethodsMap; | |
| 541 UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters; | |
| 542 UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters; | |
| 543 UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables; | |
| 544 UnmodifiableMapView<Symbol, Mirror> _cachedMembers; | |
| 545 UnmodifiableListView<InstanceMirror> _cachedMetadata; | |
| 514 | 546 |
| 515 // Set as side-effect of accessing JsLibraryMirror.classes. | 547 // Set as side-effect of accessing JsLibraryMirror.classes. |
| 516 JsLibraryMirror _owner; | 548 JsLibraryMirror _owner; |
| 517 | 549 |
| 518 JsClassMirror(Symbol simpleName, | 550 JsClassMirror(Symbol simpleName, |
| 519 this._mangledName, | 551 this._mangledName, |
| 520 this._jsConstructorOrInterceptor, | 552 this._jsConstructorOrInterceptor, |
| 521 this._fieldsDescriptor, | 553 this._fieldsDescriptor, |
| 522 this._fieldsMetadata) | 554 this._fieldsMetadata) |
| 523 : super(simpleName); | 555 : super(simpleName); |
| 524 | 556 |
| 525 String get _prettyName => 'ClassMirror'; | 557 String get _prettyName => 'ClassMirror'; |
| 526 | 558 |
| 527 get _jsConstructor { | 559 get _jsConstructor { |
| 528 if (_jsConstructorOrInterceptor is Interceptor) { | 560 if (_jsConstructorOrInterceptor is Interceptor) { |
| 529 return JS('', '#.constructor', _jsConstructorOrInterceptor); | 561 return JS('', '#.constructor', _jsConstructorOrInterceptor); |
| 530 } else { | 562 } else { |
| 531 return _jsConstructorOrInterceptor; | 563 return _jsConstructorOrInterceptor; |
| 532 } | 564 } |
| 533 } | 565 } |
| 534 | 566 |
| 535 Map<Symbol, MethodMirror> get constructors { | 567 Map<Symbol, MethodMirror> get constructors { |
| 536 var result = new Map<Symbol, MethodMirror>(); | 568 if (_cachedConstructors != null) return _cachedConstructors; |
| 569 var result = new Map(); | |
| 537 for (JsMethodMirror method in _methods) { | 570 for (JsMethodMirror method in _methods) { |
| 538 if (method.isConstructor) { | 571 if (method.isConstructor) { |
| 539 result[method.simpleName] = method; | 572 result[method.simpleName] = method; |
| 540 } | 573 } |
| 541 } | 574 } |
| 542 return result; | 575 return _cachedConstructors = |
| 576 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 543 } | 577 } |
| 544 | 578 |
| 545 List<JsMethodMirror> get _methods { | 579 List<JsMethodMirror> get _methods { |
| 546 if (_cachedMethods != null) return _cachedMethods; | 580 if (_cachedMethods != null) return _cachedMethods; |
| 547 var prototype = JS('', '#.prototype', _jsConstructor); | 581 var prototype = JS('', '#.prototype', _jsConstructor); |
| 548 List<String> keys = extractKeys(prototype); | 582 List<String> keys = extractKeys(prototype); |
| 549 var result = <JsMethodMirror>[]; | 583 var result = <JsMethodMirror>[]; |
| 550 for (String key in keys) { | 584 for (String key in keys) { |
| 551 if (key == '') continue; | 585 if (key == '') continue; |
| 552 String simpleName = mangledNames[key]; | 586 String simpleName = mangledNames[key]; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 var staticDescriptor = JS('', 'init.statics[#]', _mangledName); | 645 var staticDescriptor = JS('', 'init.statics[#]', _mangledName); |
| 612 if (staticDescriptor != null) { | 646 if (staticDescriptor != null) { |
| 613 parseCompactFieldSpecification( | 647 parseCompactFieldSpecification( |
| 614 this, JS('', '#[""]', staticDescriptor), true, result); | 648 this, JS('', '#[""]', staticDescriptor), true, result); |
| 615 } | 649 } |
| 616 _cachedFields = result; | 650 _cachedFields = result; |
| 617 return _cachedFields; | 651 return _cachedFields; |
| 618 } | 652 } |
| 619 | 653 |
| 620 Map<Symbol, MethodMirror> get methods { | 654 Map<Symbol, MethodMirror> get methods { |
| 621 var result = new Map<Symbol, MethodMirror>(); | 655 if (_cachedMethodsMap != null) return _cachedMethodsMap; |
| 656 var result = new Map(); | |
| 622 for (JsMethodMirror method in _methods) { | 657 for (JsMethodMirror method in _methods) { |
| 623 if (!method.isConstructor && !method.isGetter && !method.isSetter) { | 658 if (!method.isConstructor && !method.isGetter && !method.isSetter) { |
| 624 result[method.simpleName] = method; | 659 result[method.simpleName] = method; |
| 625 } | 660 } |
| 626 } | 661 } |
| 627 return result; | 662 return _cachedMethodsMap = |
| 663 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 628 } | 664 } |
| 629 | 665 |
| 630 Map<Symbol, MethodMirror> get getters { | 666 Map<Symbol, MethodMirror> get getters { |
| 667 if (_cachedGetters != null) return _cachedGetters; | |
| 631 // TODO(ahe): This is a hack to remove getters corresponding to a field. | 668 // TODO(ahe): This is a hack to remove getters corresponding to a field. |
| 632 var fields = variables; | 669 var fields = variables; |
| 633 | 670 |
| 634 var result = new Map<Symbol, MethodMirror>(); | 671 var result = new Map(); |
| 635 for (JsMethodMirror method in _methods) { | 672 for (JsMethodMirror method in _methods) { |
| 636 if (method.isGetter) { | 673 if (method.isGetter) { |
| 637 | 674 |
| 638 // TODO(ahe): This is a hack to remove getters corresponding to a field. | 675 // TODO(ahe): This is a hack to remove getters corresponding to a field. |
| 639 if (fields[method.simpleName] != null) continue; | 676 if (fields[method.simpleName] != null) continue; |
| 640 | 677 |
| 641 result[method.simpleName] = method; | 678 result[method.simpleName] = method; |
| 642 } | 679 } |
| 643 } | 680 } |
| 644 return result; | 681 return _cachedGetters = |
| 682 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 645 } | 683 } |
| 646 | 684 |
| 647 Map<Symbol, MethodMirror> get setters { | 685 Map<Symbol, MethodMirror> get setters { |
| 686 if (_cachedSetters != null) return _cachedSetters; | |
| 648 // TODO(ahe): This is a hack to remove setters corresponding to a field. | 687 // TODO(ahe): This is a hack to remove setters corresponding to a field. |
| 649 var fields = variables; | 688 var fields = variables; |
| 650 | 689 |
| 651 var result = new Map<Symbol, MethodMirror>(); | 690 var result = new Map(); |
| 652 for (JsMethodMirror method in _methods) { | 691 for (JsMethodMirror method in _methods) { |
| 653 if (method.isSetter) { | 692 if (method.isSetter) { |
| 654 | 693 |
| 655 // TODO(ahe): This is a hack to remove setters corresponding to a field. | 694 // TODO(ahe): This is a hack to remove setters corresponding to a field. |
| 656 String name = n(method.simpleName); | 695 String name = n(method.simpleName); |
| 657 name = name.substring(0, name.length - 1); // Remove '='. | 696 name = name.substring(0, name.length - 1); // Remove '='. |
| 658 if (fields[s(name)] != null) continue; | 697 if (fields[s(name)] != null) continue; |
| 659 | 698 |
| 660 result[method.simpleName] = method; | 699 result[method.simpleName] = method; |
| 661 } | 700 } |
| 662 } | 701 } |
| 663 return result; | 702 return _cachedSetters = |
| 703 new UnmodifiableMapView<Symbol, MethodMirror>(result); | |
| 664 } | 704 } |
| 665 | 705 |
| 666 Map<Symbol, VariableMirror> get variables { | 706 Map<Symbol, VariableMirror> get variables { |
| 667 var result = new Map<Symbol, VariableMirror>(); | 707 if (_cachedVariables != null) return _cachedVariables; |
| 708 var result = new Map(); | |
| 668 for (JsVariableMirror mirror in _fields) { | 709 for (JsVariableMirror mirror in _fields) { |
| 669 result[mirror.simpleName] = mirror; | 710 result[mirror.simpleName] = mirror; |
| 670 } | 711 } |
| 671 return result; | 712 return _cachedVariables = |
| 713 new UnmodifiableMapView<Symbol, VariableMirror>(result); | |
| 672 } | 714 } |
| 673 | 715 |
| 674 Map<Symbol, Mirror> get members { | 716 Map<Symbol, Mirror> get members { |
| 675 Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(variables); | 717 if (_cachedMembers != null) return _cachedMembers; |
| 718 Map<Symbol, Mirror> result = new Map.from(variables); | |
| 676 for (JsMethodMirror method in _methods) { | 719 for (JsMethodMirror method in _methods) { |
| 677 if (method.isSetter) { | 720 if (method.isSetter) { |
| 678 String name = n(method.simpleName); | 721 String name = n(method.simpleName); |
| 679 name = name.substring(0, name.length - 1); | 722 name = name.substring(0, name.length - 1); |
| 680 // Filter-out setters corresponding to variables. | 723 // Filter-out setters corresponding to variables. |
| 681 if (result[s(name)] is VariableMirror) continue; | 724 if (result[s(name)] is VariableMirror) continue; |
| 682 } | 725 } |
| 683 // Use putIfAbsent to filter-out getters corresponding to variables. | 726 // Use putIfAbsent to filter-out getters corresponding to variables. |
| 684 result.putIfAbsent(method.simpleName, () => method); | 727 result.putIfAbsent(method.simpleName, () => method); |
| 685 } | 728 } |
| 686 return result; | 729 return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result); |
| 687 } | 730 } |
| 688 | 731 |
| 689 InstanceMirror setField(Symbol fieldName, Object arg) { | 732 InstanceMirror setField(Symbol fieldName, Object arg) { |
| 690 JsVariableMirror mirror = variables[fieldName]; | 733 JsVariableMirror mirror = variables[fieldName]; |
| 691 if (mirror != null && mirror.isStatic && !mirror.isFinal) { | 734 if (mirror != null && mirror.isStatic && !mirror.isFinal) { |
| 692 String jsName = mirror._jsName; | 735 String jsName = mirror._jsName; |
| 693 if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) { | 736 if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) { |
| 694 throw new RuntimeError('Cannot find "$jsName" in current isolate.'); | 737 throw new RuntimeError('Cannot find "$jsName" in current isolate.'); |
| 695 } | 738 } |
| 696 JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg); | 739 JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 763 } | 806 } |
| 764 } | 807 } |
| 765 if (_owner == null) { | 808 if (_owner == null) { |
| 766 throw new StateError('Class "${n(simpleName)}" has no owner'); | 809 throw new StateError('Class "${n(simpleName)}" has no owner'); |
| 767 } | 810 } |
| 768 } | 811 } |
| 769 return _owner; | 812 return _owner; |
| 770 } | 813 } |
| 771 | 814 |
| 772 List<InstanceMirror> get metadata { | 815 List<InstanceMirror> get metadata { |
| 816 if (_cachedMetadata != null) return _cachedMetadata; | |
| 773 if (_metadata == null) { | 817 if (_metadata == null) { |
| 774 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); | 818 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); |
| 775 } | 819 } |
| 776 return _metadata.map(reflect).toList(); | 820 return _cachedMetadata = |
| 821 new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect)); | |
| 777 } | 822 } |
| 778 | 823 |
| 779 ClassMirror get superclass { | 824 ClassMirror get superclass { |
| 780 if (_superclass == null) { | 825 if (_superclass == null) { |
| 781 var superclassName = _fieldsDescriptor.split(';')[0]; | 826 var superclassName = _fieldsDescriptor.split(';')[0]; |
| 782 // Use _superclass == this to represent class with no superclass (Object). | 827 // Use _superclass == this to represent class with no superclass (Object). |
| 783 _superclass = (superclassName == '') | 828 _superclass = (superclassName == '') |
| 784 ? this : reflectClassByMangledName(superclassName); | 829 ? this : reflectClassByMangledName(superclassName); |
| 785 } | 830 } |
| 786 return _superclass == this ? null : _superclass; | 831 return _superclass == this ? null : _superclass; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 967 final _jsFunction; | 1012 final _jsFunction; |
| 968 final int _parameterCount; | 1013 final int _parameterCount; |
| 969 final bool isGetter; | 1014 final bool isGetter; |
| 970 final bool isSetter; | 1015 final bool isSetter; |
| 971 final bool isStatic; | 1016 final bool isStatic; |
| 972 final bool isConstructor; | 1017 final bool isConstructor; |
| 973 final bool isOperator; | 1018 final bool isOperator; |
| 974 DeclarationMirror _owner; | 1019 DeclarationMirror _owner; |
| 975 List _metadata; | 1020 List _metadata; |
| 976 var _returnType; | 1021 var _returnType; |
| 977 var _parameters; | 1022 UnmodifiableListView<ParameterMirror> _parameters; |
| 978 | 1023 |
| 979 JsMethodMirror(Symbol simpleName, | 1024 JsMethodMirror(Symbol simpleName, |
| 980 this._jsFunction, | 1025 this._jsFunction, |
| 981 this._parameterCount, | 1026 this._parameterCount, |
| 982 this.isGetter, | 1027 this.isGetter, |
| 983 this.isSetter, | 1028 this.isSetter, |
| 984 this.isStatic, | 1029 this.isStatic, |
| 985 this.isConstructor, | 1030 this.isConstructor, |
| 986 this.isOperator) | 1031 this.isOperator) |
| 987 : super(simpleName); | 1032 : super(simpleName); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1009 optionalParameterCount = int.parse(info[2]); | 1054 optionalParameterCount = int.parse(info[2]); |
| 1010 } | 1055 } |
| 1011 return new JsMethodMirror( | 1056 return new JsMethodMirror( |
| 1012 s(name), jsFunction, requiredParameterCount + optionalParameterCount, | 1057 s(name), jsFunction, requiredParameterCount + optionalParameterCount, |
| 1013 isGetter, isSetter, isStatic, isConstructor, isOperator); | 1058 isGetter, isSetter, isStatic, isConstructor, isOperator); |
| 1014 } | 1059 } |
| 1015 | 1060 |
| 1016 String get _prettyName => 'MethodMirror'; | 1061 String get _prettyName => 'MethodMirror'; |
| 1017 | 1062 |
| 1018 List<ParameterMirror> get parameters { | 1063 List<ParameterMirror> get parameters { |
| 1064 if (_parameters != null) return _parameters; | |
| 1019 metadata; // Compute _parameters as a side-effect of extracting metadata. | 1065 metadata; // Compute _parameters as a side-effect of extracting metadata. |
| 1020 return new List<ParameterMirror>.from(_parameters); | 1066 return _parameters; |
| 1021 } | 1067 } |
| 1022 | 1068 |
| 1023 DeclarationMirror get owner => _owner; | 1069 DeclarationMirror get owner => _owner; |
| 1024 | 1070 |
| 1025 TypeMirror get returnType { | 1071 TypeMirror get returnType { |
| 1026 metadata; // Compute _returnType as a side-effect of extracting metadata. | 1072 metadata; // Compute _returnType as a side-effect of extracting metadata. |
| 1027 return typeMirrorFromRuntimeTypeRepresentation(_returnType); | 1073 return typeMirrorFromRuntimeTypeRepresentation(_returnType); |
| 1028 } | 1074 } |
| 1029 | 1075 |
| 1030 List<InstanceMirror> get metadata { | 1076 List<InstanceMirror> get metadata { |
| 1031 if (_metadata == null) { | 1077 if (_metadata == null) { |
| 1032 var raw = extractMetadata(_jsFunction); | 1078 var raw = extractMetadata(_jsFunction); |
| 1033 _returnType = raw[0]; | 1079 var formals = new List(_parameterCount); |
| 1034 int parameterLength = 1 + _parameterCount * 2; | 1080 if (!raw.isEmpty) { |
| 1035 var formals = new List<ParameterMirror>(_parameterCount); | 1081 _returnType = raw[0]; |
| 1036 int formalsCount = 0; | 1082 int parameterLength = 1 + _parameterCount * 2; |
| 1037 for (int i = 1; i < parameterLength; i += 2) { | 1083 int formalsCount = 0; |
| 1038 var name = raw[i]; | 1084 for (int i = 1; i < parameterLength; i += 2) { |
| 1039 var type = raw[i + 1]; | 1085 var name = raw[i]; |
| 1040 formals[formalsCount++] = new JsParameterMirror(name, this, type); | 1086 var type = raw[i + 1]; |
| 1087 formals[formalsCount++] = new JsParameterMirror(name, this, type); | |
| 1088 } | |
| 1089 raw = raw.sublist(parameterLength); | |
| 1090 } else { | |
| 1091 for (int i = 0; i < _parameterCount; i++) { | |
| 1092 formals[i] = new JsParameterMirror('argument$i', this, null); | |
| 1093 } | |
| 1041 } | 1094 } |
| 1042 _parameters = formals; | 1095 _parameters = new UnmodifiableListView<ParameterMirror>(formals); |
| 1043 _metadata = raw.sublist(parameterLength); | 1096 _metadata = new UnmodifiableListView(raw.map(reflect)); |
| 1044 } | 1097 } |
| 1045 return _metadata.map(reflect).toList(); | 1098 return _metadata; |
| 1046 } | 1099 } |
| 1047 | 1100 |
| 1048 Symbol get constructorName { | 1101 Symbol get constructorName { |
| 1049 // TODO(ahe): I believe it is more appropriate to throw an exception or | 1102 // TODO(ahe): I believe it is more appropriate to throw an exception or |
| 1050 // return null. | 1103 // return null. |
| 1051 if (!isConstructor) return const Symbol(''); | 1104 if (!isConstructor) return const Symbol(''); |
| 1052 String name = n(simpleName); | 1105 String name = n(simpleName); |
| 1053 int index = name.indexOf('.'); | 1106 int index = name.indexOf('.'); |
| 1054 if (index == -1) return const Symbol(''); | 1107 if (index == -1) return const Symbol(''); |
| 1055 return s(name.substring(index + 1)); | 1108 return s(name.substring(index + 1)); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1215 case '|': | 1268 case '|': |
| 1216 case '-': | 1269 case '-': |
| 1217 case 'unary-': | 1270 case 'unary-': |
| 1218 case '[]=': | 1271 case '[]=': |
| 1219 case '~': | 1272 case '~': |
| 1220 return true; | 1273 return true; |
| 1221 default: | 1274 default: |
| 1222 return false; | 1275 return false; |
| 1223 } | 1276 } |
| 1224 } | 1277 } |
| 1278 | |
| 1279 // Copied from package "unmodifiable_collection". | |
| 1280 // TODO(ahe): Lobby to get it added to dart:collection. | |
| 1281 class UnmodifiableMapView<K, V> implements Map<K, V> { | |
| 1282 Map<K, V> _source; | |
| 1283 UnmodifiableMapView(Map<K, V> source) : _source = source; | |
| 1284 | |
| 1285 static void _throw() { | |
| 1286 throw new UnsupportedError("Cannot modify an unmodifiable Map"); | |
| 1287 } | |
| 1288 | |
| 1289 int get length => _source.length; | |
| 1290 | |
| 1291 bool get isEmpty => _source.isEmpty; | |
| 1292 | |
| 1293 bool get isNotEmpty => _source.isNotEmpty; | |
| 1294 | |
| 1295 V operator [](K key) => _source[key]; | |
| 1296 | |
| 1297 bool containsKey(K key) => _source.containsKey(key); | |
| 1298 | |
| 1299 bool containsValue(V value) => _source.containsValue(value); | |
| 1300 | |
| 1301 void forEach(void f(K key, V value)) => _source.forEach(f); | |
| 1302 | |
| 1303 Iterable<K> get keys => _source.keys; | |
| 1304 | |
| 1305 Iterable<V> get values => _source.values; | |
| 1306 | |
| 1307 | |
| 1308 void operator []=(K key, V value) => _throw(); | |
| 1309 | |
| 1310 V putIfAbsent(K key, V ifAbsent()) { _throw(); } | |
|
kustermann
2013/08/12 17:07:01
Why do you use once {} and once => ?
ahe
2013/08/12 17:10:21
I don't know, this is a verbatim copy from the pac
| |
| 1311 | |
| 1312 void addAll(Map<K, V> other) => _throw(); | |
| 1313 | |
| 1314 V remove(K key) { _throw(); } | |
| 1315 | |
| 1316 void clear() => _throw(); | |
| 1317 } | |
| OLD | NEW |