| 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:mirrors'; | 8 import 'dart:mirrors'; |
| 9 | 9 |
| 10 import 'dart:_foreign_helper' show JS, JS_CURRENT_ISOLATE; | 10 import 'dart:_foreign_helper' show JS, JS_CURRENT_ISOLATE; |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}'; | 397 String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}'; |
| 398 | 398 |
| 399 // TODO(ahe): Remove this method from the API. | 399 // TODO(ahe): Remove this method from the API. |
| 400 MirrorSystem get mirrors => currentJsMirrorSystem; | 400 MirrorSystem get mirrors => currentJsMirrorSystem; |
| 401 } | 401 } |
| 402 | 402 |
| 403 class JsClassMirror extends JsTypeMirror with JsObjectMirror | 403 class JsClassMirror extends JsTypeMirror with JsObjectMirror |
| 404 implements ClassMirror { | 404 implements ClassMirror { |
| 405 final String _mangledName; | 405 final String _mangledName; |
| 406 final _jsConstructorOrInterceptor; | 406 final _jsConstructorOrInterceptor; |
| 407 final String _fields; | 407 final String _fieldsDescriptor; |
| 408 final List _fieldsMetadata; | 408 final List _fieldsMetadata; |
| 409 List _metadata; | 409 List _metadata; |
| 410 JsClassMirror _superclass; | 410 JsClassMirror _superclass; |
| 411 List<JsMethodMirror> _cachedMethods; | 411 List<JsMethodMirror> _cachedMethods; |
| 412 List<JsVariableMirror> _cachedFields; |
| 412 | 413 |
| 413 // Set as side-effect of accessing JsLibraryMirror.classes. | 414 // Set as side-effect of accessing JsLibraryMirror.classes. |
| 414 JsLibraryMirror _owner; | 415 JsLibraryMirror _owner; |
| 415 | 416 |
| 416 JsClassMirror(Symbol simpleName, | 417 JsClassMirror(Symbol simpleName, |
| 417 this._mangledName, | 418 this._mangledName, |
| 418 this._jsConstructorOrInterceptor, | 419 this._jsConstructorOrInterceptor, |
| 419 this._fields, | 420 this._fieldsDescriptor, |
| 420 this._fieldsMetadata) | 421 this._fieldsMetadata) |
| 421 : super(simpleName); | 422 : super(simpleName); |
| 422 | 423 |
| 423 String get _prettyName => 'ClassMirror'; | 424 String get _prettyName => 'ClassMirror'; |
| 424 | 425 |
| 425 get _jsConstructor { | 426 get _jsConstructor { |
| 426 if (_jsConstructorOrInterceptor is Interceptor) { | 427 if (_jsConstructorOrInterceptor is Interceptor) { |
| 427 return JS('', '#.constructor', _jsConstructorOrInterceptor); | 428 return JS('', '#.constructor', _jsConstructorOrInterceptor); |
| 428 } else { | 429 } else { |
| 429 return _jsConstructorOrInterceptor; | 430 return _jsConstructorOrInterceptor; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 JsMethodMirror mirror = | 488 JsMethodMirror mirror = |
| 488 new JsMethodMirror.fromUnmangledName( | 489 new JsMethodMirror.fromUnmangledName( |
| 489 unmangledName, jsFunction, isStatic, isConstructor); | 490 unmangledName, jsFunction, isStatic, isConstructor); |
| 490 result.add(mirror); | 491 result.add(mirror); |
| 491 mirror._owner = this; | 492 mirror._owner = this; |
| 492 } | 493 } |
| 493 | 494 |
| 494 return _cachedMethods = result; | 495 return _cachedMethods = result; |
| 495 } | 496 } |
| 496 | 497 |
| 498 List<VariableMirror> get _fields { |
| 499 if (_cachedFields != null) return _cachedFields; |
| 500 var result = <VariableMirror>[]; |
| 501 var s = _fieldsDescriptor.split(';'); |
| 502 var fields = s[1] == '' ? [] : s[1].split(','); |
| 503 int fieldNumber = 0; |
| 504 for (String field in fields) { |
| 505 var metadata; |
| 506 if (_fieldsMetadata != null) { |
| 507 metadata = _fieldsMetadata[fieldNumber++]; |
| 508 } |
| 509 JsVariableMirror mirror = |
| 510 new JsVariableMirror.from(field, metadata, this, false); |
| 511 if (mirror != null) { |
| 512 result.add(mirror); |
| 513 } |
| 514 } |
| 515 |
| 516 var staticDescriptor = JS('', 'init.statics[#]', _mangledName); |
| 517 if (staticDescriptor != null) { |
| 518 var staticFieldsDescriptor = JS('', '#[""]', staticDescriptor); |
| 519 var staticFieldsMetadata = null; |
| 520 var staticFields; |
| 521 if (staticFieldsDescriptor is List) { |
| 522 staticFields = staticFieldsDescriptor[0].split(','); |
| 523 staticFieldsMetadata = staticFieldsDescriptor.sublist(1); |
| 524 } else if (staticFieldsDescriptor is String) { |
| 525 staticFields = staticFieldsDescriptor.split(','); |
| 526 } else { |
| 527 staticFields = []; |
| 528 } |
| 529 fieldNumber = 0; |
| 530 for (String staticField in staticFields) { |
| 531 var metadata; |
| 532 if (staticFieldsMetadata != null) { |
| 533 metadata = staticFieldsMetadata[fieldNumber++]; |
| 534 } |
| 535 JsVariableMirror mirror = |
| 536 new JsVariableMirror.from(staticField, metadata, this, true); |
| 537 if (mirror != null) { |
| 538 result.add(mirror); |
| 539 } |
| 540 } |
| 541 } |
| 542 _cachedFields = result; |
| 543 return _cachedFields; |
| 544 } |
| 545 |
| 497 Map<Symbol, MethodMirror> get methods { | 546 Map<Symbol, MethodMirror> get methods { |
| 498 var result = new Map<Symbol, MethodMirror>(); | 547 var result = new Map<Symbol, MethodMirror>(); |
| 499 for (JsMethodMirror method in _methods) { | 548 for (JsMethodMirror method in _methods) { |
| 500 if (!method.isConstructor && !method.isGetter && !method.isSetter) { | 549 if (!method.isConstructor && !method.isGetter && !method.isSetter) { |
| 501 result[method.simpleName] = method; | 550 result[method.simpleName] = method; |
| 502 } | 551 } |
| 503 } | 552 } |
| 504 return result; | 553 return result; |
| 505 } | 554 } |
| 506 | 555 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 536 if (fields[s(name)] != null) continue; | 585 if (fields[s(name)] != null) continue; |
| 537 | 586 |
| 538 result[method.simpleName] = method; | 587 result[method.simpleName] = method; |
| 539 } | 588 } |
| 540 } | 589 } |
| 541 return result; | 590 return result; |
| 542 } | 591 } |
| 543 | 592 |
| 544 Map<Symbol, VariableMirror> get variables { | 593 Map<Symbol, VariableMirror> get variables { |
| 545 var result = new Map<Symbol, VariableMirror>(); | 594 var result = new Map<Symbol, VariableMirror>(); |
| 546 var s = _fields.split(';'); | 595 for (JsVariableMirror mirror in _fields) { |
| 547 var fields = s[1] == '' ? [] : s[1].split(','); | 596 result[mirror.simpleName] = mirror; |
| 548 int fieldNumber = 0; | |
| 549 for (String field in fields) { | |
| 550 var metadata; | |
| 551 if (_fieldsMetadata != null) { | |
| 552 metadata = _fieldsMetadata[fieldNumber++]; | |
| 553 } | |
| 554 JsVariableMirror mirror = | |
| 555 new JsVariableMirror.from(field, metadata, this); | |
| 556 if (mirror != null) { | |
| 557 result[mirror.simpleName] = mirror; | |
| 558 } | |
| 559 } | 597 } |
| 560 return result; | 598 return result; |
| 561 } | 599 } |
| 562 | 600 |
| 563 Map<Symbol, Mirror> get members { | 601 Map<Symbol, Mirror> get members { |
| 564 Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(variables); | 602 Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(variables); |
| 565 for (JsMethodMirror method in _methods) { | 603 for (JsMethodMirror method in _methods) { |
| 566 if (method.isSetter) { | 604 if (method.isSetter) { |
| 567 String name = n(method.simpleName); | 605 String name = n(method.simpleName); |
| 568 name = name.substring(0, name.length - 1); | 606 name = name.substring(0, name.length - 1); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 | 689 |
| 652 List<InstanceMirror> get metadata { | 690 List<InstanceMirror> get metadata { |
| 653 if (_metadata == null) { | 691 if (_metadata == null) { |
| 654 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); | 692 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); |
| 655 } | 693 } |
| 656 return _metadata.map(reflect).toList(); | 694 return _metadata.map(reflect).toList(); |
| 657 } | 695 } |
| 658 | 696 |
| 659 ClassMirror get superclass { | 697 ClassMirror get superclass { |
| 660 if (_superclass == null) { | 698 if (_superclass == null) { |
| 661 var superclassName = _fields.split(';')[0]; | 699 var superclassName = _fieldsDescriptor.split(';')[0]; |
| 662 // Use _superclass == this to represent class with no superclass (Object). | 700 // Use _superclass == this to represent class with no superclass (Object). |
| 663 _superclass = (superclassName == '') | 701 _superclass = (superclassName == '') |
| 664 ? this : reflectClassByMangledName(superclassName); | 702 ? this : reflectClassByMangledName(superclassName); |
| 665 } | 703 } |
| 666 return _superclass == this ? null : _superclass; | 704 return _superclass == this ? null : _superclass; |
| 667 } | 705 } |
| 668 | 706 |
| 669 // TODO(ahe): Implement these; | 707 // TODO(ahe): Implement these; |
| 670 InstanceMirror invoke(Symbol memberName, | 708 InstanceMirror invoke(Symbol memberName, |
| 671 List positionalArguments, | 709 List positionalArguments, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 694 JsVariableMirror(Symbol simpleName, | 732 JsVariableMirror(Symbol simpleName, |
| 695 this._jsName, | 733 this._jsName, |
| 696 this.isFinal, | 734 this.isFinal, |
| 697 this.isStatic, | 735 this.isStatic, |
| 698 this._metadataFunction, | 736 this._metadataFunction, |
| 699 this._owner) | 737 this._owner) |
| 700 : super(simpleName); | 738 : super(simpleName); |
| 701 | 739 |
| 702 factory JsVariableMirror.from(String descriptor, | 740 factory JsVariableMirror.from(String descriptor, |
| 703 metadataFunction, | 741 metadataFunction, |
| 704 JsClassMirror owner) { | 742 JsClassMirror owner, |
| 743 bool isStatic) { |
| 705 int length = descriptor.length; | 744 int length = descriptor.length; |
| 706 var code = fieldCode(descriptor.codeUnitAt(length - 1)); | 745 var code = fieldCode(descriptor.codeUnitAt(length - 1)); |
| 707 bool isFinal = false; | 746 bool isFinal = false; |
| 708 if (code == 0) return null; // Inherited field. | 747 if (code == 0) return null; // Inherited field. |
| 709 bool hasGetter = (code & 3) != 0; | 748 bool hasGetter = (code & 3) != 0; |
| 710 bool hasSetter = (code >> 2) != 0; | 749 bool hasSetter = (code >> 2) != 0; |
| 711 isFinal = !hasSetter; | 750 isFinal = !hasSetter; |
| 712 length--; | 751 length--; |
| 713 String jsName; | 752 String jsName; |
| 714 String accessorName = jsName = descriptor.substring(0, length); | 753 String accessorName = jsName = descriptor.substring(0, length); |
| 715 int divider = descriptor.indexOf(':'); | 754 int divider = descriptor.indexOf(':'); |
| 716 if (divider > 0) { | 755 if (divider > 0) { |
| 717 accessorName = accessorName.substring(0, divider); | 756 accessorName = accessorName.substring(0, divider); |
| 718 jsName = accessorName.substring(divider + 1); | 757 jsName = accessorName.substring(divider + 1); |
| 719 } | 758 } |
| 759 var unmangledName = |
| 760 (isStatic ? mangledGlobalNames : mangledNames)[accessorName]; |
| 761 if (unmangledName == null) unmangledName = accessorName; |
| 720 if (!hasSetter) { | 762 if (!hasSetter) { |
| 721 // TODO(ahe): This is a hack to handle checked setters in checked mode. | 763 // TODO(ahe): This is a hack to handle checked setters in checked mode. |
| 722 var setterName = s('$accessorName='); | 764 var setterName = s('$accessorName='); |
| 723 for (JsMethodMirror method in owner._methods) { | 765 for (JsMethodMirror method in owner._methods) { |
| 724 if (method.simpleName == setterName) { | 766 if (method.simpleName == setterName) { |
| 725 isFinal = false; | 767 isFinal = false; |
| 726 break; | 768 break; |
| 727 } | 769 } |
| 728 } | 770 } |
| 729 } | 771 } |
| 730 return new JsVariableMirror( | 772 return new JsVariableMirror( |
| 731 s(accessorName), jsName, isFinal, false, metadataFunction, owner); | 773 s(unmangledName), jsName, isFinal, isStatic, metadataFunction, owner); |
| 732 } | 774 } |
| 733 | 775 |
| 734 String get _prettyName => 'VariableMirror'; | 776 String get _prettyName => 'VariableMirror'; |
| 735 | 777 |
| 736 // TODO(ahe): Improve this information and test it. | 778 // TODO(ahe): Improve this information and test it. |
| 737 TypeMirror get type => JsMirrorSystem._dynamicType; | 779 TypeMirror get type => JsMirrorSystem._dynamicType; |
| 738 | 780 |
| 739 DeclarationMirror get owner => _owner; | 781 DeclarationMirror get owner => _owner; |
| 740 | 782 |
| 741 List<InstanceMirror> get metadata { | 783 List<InstanceMirror> get metadata { |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 var metadataFunction = JS('', '#["@"]', victim); | 1000 var metadataFunction = JS('', '#["@"]', victim); |
| 959 if (metadataFunction != null) return JS('', '#()', metadataFunction); | 1001 if (metadataFunction != null) return JS('', '#()', metadataFunction); |
| 960 String source = JS('String', 'Function.prototype.toString.call(#)', victim); | 1002 String source = JS('String', 'Function.prototype.toString.call(#)', victim); |
| 961 int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}')); | 1003 int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}')); |
| 962 if (index == -1) return const []; | 1004 if (index == -1) return const []; |
| 963 index++; | 1005 index++; |
| 964 int endQuote = source.indexOf('"', index); | 1006 int endQuote = source.indexOf('"', index); |
| 965 return source.substring(index, endQuote).split(',').map(int.parse).map( | 1007 return source.substring(index, endQuote).split(',').map(int.parse).map( |
| 966 (int i) => JS('', 'init.metadata[#]', i)).toList(); | 1008 (int i) => JS('', 'init.metadata[#]', i)).toList(); |
| 967 } | 1009 } |
| OLD | NEW |