| OLD | NEW |
| 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 | 2 |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
| 7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2848 isStatic: isStatic, type: type, element: element); | 2848 isStatic: isStatic, type: type, element: element); |
| 2849 | 2849 |
| 2850 if (isStatic) { | 2850 if (isStatic) { |
| 2851 var dynType = _emitStaticAccess(type); | 2851 var dynType = _emitStaticAccess(type); |
| 2852 return new JS.PropertyAccess(dynType, member); | 2852 return new JS.PropertyAccess(dynType, member); |
| 2853 } | 2853 } |
| 2854 | 2854 |
| 2855 // For instance members, we add implicit-this. | 2855 // For instance members, we add implicit-this. |
| 2856 // For method tear-offs, we ensure it's a bound method. | 2856 // For method tear-offs, we ensure it's a bound method. |
| 2857 var tearOff = element is MethodElement && !inInvocationContext(node); | 2857 var tearOff = element is MethodElement && !inInvocationContext(node); |
| 2858 if (tearOff) return _callHelper('bind(this, #)', member); | 2858 if (tearOff) { |
| 2859 // To be safe always use the symbolized name when binding on a native |
| 2860 // class as bind assumes the name will match the name class sigatures |
| 2861 // which is symbolized for native classes. |
| 2862 var safeName = _emitMemberName(name, |
| 2863 isStatic: isStatic, |
| 2864 type: type, |
| 2865 element: element, |
| 2866 alwaysSymbolizeNative: true); |
| 2867 return _callHelper('bind(this, #)', safeName); |
| 2868 } |
| 2859 return js.call('this.#', member); | 2869 return js.call('this.#', member); |
| 2860 } | 2870 } |
| 2861 | 2871 |
| 2862 if (element is ParameterElement) { | 2872 if (element is ParameterElement) { |
| 2863 return _emitParameter(element); | 2873 return _emitParameter(element); |
| 2864 } | 2874 } |
| 2865 | 2875 |
| 2866 // If this is one of our compiler's temporary variables, return its JS form. | 2876 // If this is one of our compiler's temporary variables, return its JS form. |
| 2867 if (element is TemporaryVariableElement) { | 2877 if (element is TemporaryVariableElement) { |
| 2868 return element.jsVariable; | 2878 return element.jsVariable; |
| (...skipping 2146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5015 member is FieldElementImpl && | 5025 member is FieldElementImpl && |
| 5016 !member.isVirtual) { | 5026 !member.isVirtual) { |
| 5017 // If super.x is a sealed field, then x is an instance property since | 5027 // If super.x is a sealed field, then x is an instance property since |
| 5018 // subclasses cannot override x. | 5028 // subclasses cannot override x. |
| 5019 jsTarget = new JS.This(); | 5029 jsTarget = new JS.This(); |
| 5020 } | 5030 } |
| 5021 | 5031 |
| 5022 JS.Expression result; | 5032 JS.Expression result; |
| 5023 if (member != null && member is MethodElement && !isStatic) { | 5033 if (member != null && member is MethodElement && !isStatic) { |
| 5024 // Tear-off methods: explicitly bind it. | 5034 // Tear-off methods: explicitly bind it. |
| 5035 // To be safe always use the symbolized name when binding on a native |
| 5036 // class as bind assumes the name will match the name class sigatures |
| 5037 // which is symbolized for native classes. |
| 5038 var safeName = _emitMemberName(memberName, |
| 5039 type: getStaticType(target), |
| 5040 isStatic: isStatic, |
| 5041 element: member, |
| 5042 alwaysSymbolizeNative: true); |
| 5025 if (isSuper) { | 5043 if (isSuper) { |
| 5026 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]); | 5044 result = |
| 5045 _callHelper('bind(this, #, #.#)', [safeName, jsTarget, safeName]); |
| 5027 } else if (_isObjectMemberCall(target, memberName)) { | 5046 } else if (_isObjectMemberCall(target, memberName)) { |
| 5028 result = _callHelper('bind(#, #, #.#)', | 5047 result = _callHelper('bind(#, #, #.#)', |
| 5029 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); | 5048 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); |
| 5030 } else { | 5049 } else { |
| 5031 result = _callHelper('bind(#, #)', [jsTarget, name]); | 5050 result = _callHelper('bind(#, #)', [jsTarget, safeName]); |
| 5032 } | 5051 } |
| 5033 } else if (_isObjectMemberCall(target, memberName)) { | 5052 } else if (_isObjectMemberCall(target, memberName)) { |
| 5034 result = _callHelper('#(#)', [memberName, jsTarget]); | 5053 result = _callHelper('#(#)', [memberName, jsTarget]); |
| 5035 } else { | 5054 } else { |
| 5036 result = js.call('#.#', [jsTarget, name]); | 5055 result = js.call('#.#', [jsTarget, name]); |
| 5037 } | 5056 } |
| 5038 if (typeArgs == null) { | 5057 if (typeArgs == null) { |
| 5039 return result; | 5058 return result; |
| 5040 } | 5059 } |
| 5041 return _callHelper('gbind(#, #)', [result, typeArgs]); | 5060 return _callHelper('gbind(#, #)', [result, typeArgs]); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5618 /// Unary minus looks like: `x._negate()`. | 5637 /// Unary minus looks like: `x._negate()`. |
| 5619 /// | 5638 /// |
| 5620 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 5639 /// Equality is a bit special, it is generated via the Dart `equals` runtime |
| 5621 /// helper, that checks for null. The user defined method is called '=='. | 5640 /// helper, that checks for null. The user defined method is called '=='. |
| 5622 /// | 5641 /// |
| 5623 JS.Expression _emitMemberName(String name, | 5642 JS.Expression _emitMemberName(String name, |
| 5624 {DartType type, | 5643 {DartType type, |
| 5625 bool isStatic: false, | 5644 bool isStatic: false, |
| 5626 bool useExtension, | 5645 bool useExtension, |
| 5627 bool useDisplayName: false, | 5646 bool useDisplayName: false, |
| 5647 bool alwaysSymbolizeNative: false, |
| 5628 Element element}) { | 5648 Element element}) { |
| 5629 // Static members skip the rename steps and may require JS interop renames. | 5649 // Static members skip the rename steps and may require JS interop renames. |
| 5630 if (isStatic) { | 5650 if (isStatic) { |
| 5631 return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); | 5651 return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); |
| 5632 } | 5652 } |
| 5633 | 5653 |
| 5634 if (name.startsWith('_')) { | 5654 if (name.startsWith('_')) { |
| 5635 return _emitPrivateNameSymbol(currentLibrary, name); | 5655 return _emitPrivateNameSymbol(currentLibrary, name); |
| 5636 } | 5656 } |
| 5637 | 5657 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5656 } | 5676 } |
| 5657 | 5677 |
| 5658 var result = _propertyName(name); | 5678 var result = _propertyName(name); |
| 5659 | 5679 |
| 5660 if (useExtension == null) { | 5680 if (useExtension == null) { |
| 5661 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. | 5681 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. |
| 5662 var baseType = type; | 5682 var baseType = type; |
| 5663 while (baseType is TypeParameterType) { | 5683 while (baseType is TypeParameterType) { |
| 5664 baseType = (baseType.element as TypeParameterElement).bound; | 5684 baseType = (baseType.element as TypeParameterElement).bound; |
| 5665 } | 5685 } |
| 5666 useExtension = | 5686 useExtension = baseType is InterfaceType && |
| 5667 baseType is InterfaceType && _isSymbolizedMember(baseType, name); | 5687 _isSymbolizedMember(baseType, name, alwaysSymbolizeNative); |
| 5668 } | 5688 } |
| 5669 | 5689 |
| 5670 return useExtension | 5690 return useExtension |
| 5671 ? js.call('#.#', [_extensionSymbolsModule, result]) | 5691 ? js.call('#.#', [_extensionSymbolsModule, result]) |
| 5672 : result; | 5692 : result; |
| 5673 } | 5693 } |
| 5674 | 5694 |
| 5675 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); | 5695 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); |
| 5676 Element _lookupForwardedMember(ClassElement element, String name) { | 5696 Element _lookupForwardedMember(ClassElement element, String name) { |
| 5677 // We only care about public methods. | 5697 // We only care about public methods. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5694 return member; | 5714 return member; |
| 5695 } | 5715 } |
| 5696 | 5716 |
| 5697 /// Don't symbolize native members that just forward to the underlying | 5717 /// Don't symbolize native members that just forward to the underlying |
| 5698 /// native member. We limit this to non-renamed members as the receiver | 5718 /// native member. We limit this to non-renamed members as the receiver |
| 5699 /// may be a mock type. | 5719 /// may be a mock type. |
| 5700 /// | 5720 /// |
| 5701 /// Note, this is an underlying assumption here that, if another native type | 5721 /// Note, this is an underlying assumption here that, if another native type |
| 5702 /// subtypes this one, it also forwards this member to its underlying native | 5722 /// subtypes this one, it also forwards this member to its underlying native |
| 5703 /// one without renaming. | 5723 /// one without renaming. |
| 5704 bool _isSymbolizedMember(InterfaceType type, String name) { | 5724 bool _isSymbolizedMember( |
| 5725 InterfaceType type, String name, bool alwaysSymbolizeNative) { |
| 5705 // Object members are handled separately. | 5726 // Object members are handled separately. |
| 5706 if (isObjectMember(name)) { | 5727 if (isObjectMember(name)) { |
| 5707 return false; | 5728 return false; |
| 5708 } | 5729 } |
| 5709 | 5730 |
| 5710 var element = type.element; | 5731 var element = type.element; |
| 5711 if (_extensionTypes.isNativeClass(element)) { | 5732 if (_extensionTypes.isNativeClass(element)) { |
| 5712 var member = _lookupForwardedMember(element, name); | 5733 var member = _lookupForwardedMember(element, name); |
| 5713 | 5734 |
| 5714 // Fields on a native class are implicitly native. | 5735 // Fields on a native class are implicitly native. |
| 5715 // Methods/getters/setters are marked external/native. | 5736 // Methods/getters/setters are marked external/native. |
| 5716 if (member is FieldElement || | 5737 if (member is FieldElement || |
| 5717 member is ExecutableElement && member.isExternal) { | 5738 member is ExecutableElement && member.isExternal) { |
| 5718 var jsName = getAnnotationName(member, isJsName); | 5739 var jsName = getAnnotationName(member, isJsName); |
| 5719 return jsName != null && jsName != name; | 5740 return alwaysSymbolizeNative || (jsName != null && jsName != name); |
| 5720 } else { | 5741 } else { |
| 5721 // Non-external members must be symbolized. | 5742 // Non-external members must be symbolized. |
| 5722 return true; | 5743 return true; |
| 5723 } | 5744 } |
| 5724 } | 5745 } |
| 5725 // If the receiver *may* be a native type (i.e., an interface allowed to | 5746 // If the receiver *may* be a native type (i.e., an interface allowed to |
| 5726 // be implemented by a native class), conservatively symbolize - we don't | 5747 // be implemented by a native class), conservatively symbolize - we don't |
| 5727 // whether it'll be implemented via forwarding. | 5748 // whether it'll be implemented via forwarding. |
| 5728 // TODO(vsm): Consider CHA here to be less conservative. | 5749 // TODO(vsm): Consider CHA here to be less conservative. |
| 5729 return _extensionTypes.isNativeInterface(element); | 5750 return _extensionTypes.isNativeInterface(element); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6017 if (targetIdentifier.staticElement is! PrefixElement) return false; | 6038 if (targetIdentifier.staticElement is! PrefixElement) return false; |
| 6018 var prefix = targetIdentifier.staticElement as PrefixElement; | 6039 var prefix = targetIdentifier.staticElement as PrefixElement; |
| 6019 | 6040 |
| 6020 // The library the prefix is referring to must come from a deferred import. | 6041 // The library the prefix is referring to must come from a deferred import. |
| 6021 var containingLibrary = resolutionMap | 6042 var containingLibrary = resolutionMap |
| 6022 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 6043 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
| 6023 .library; | 6044 .library; |
| 6024 var imports = containingLibrary.getImportsWithPrefix(prefix); | 6045 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 6025 return imports.length == 1 && imports[0].isDeferred; | 6046 return imports.length == 1 && imports[0].isDeferred; |
| 6026 } | 6047 } |
| OLD | NEW |