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

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2691433004: Support virtual fields in DDC without requiring the @virtual annotation.
Patch Set: Created 3 years, 10 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
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 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 92
93 /// In an async* function, this represents the stream controller parameter. 93 /// In an async* function, this represents the stream controller parameter.
94 JS.TemporaryId _asyncStarController; 94 JS.TemporaryId _asyncStarController;
95 95
96 // TODO(jmesserly): fuse this with notNull check. 96 // TODO(jmesserly): fuse this with notNull check.
97 final _privateNames = 97 final _privateNames =
98 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); 98 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>();
99 final _initializingFormalTemps = 99 final _initializingFormalTemps =
100 new HashMap<ParameterElement, JS.TemporaryId>(); 100 new HashMap<ParameterElement, JS.TemporaryId>();
101 101
102 final _syntheticSuperclasses = new HashMap<ClassElement, JS.Identifier>();
103
102 JS.Identifier _extensionSymbolsModule; 104 JS.Identifier _extensionSymbolsModule;
103 JS.Identifier _runtimeModule; 105 JS.Identifier _runtimeModule;
104 final namedArgumentTemp = new JS.TemporaryId('opts'); 106 final namedArgumentTemp = new JS.TemporaryId('opts');
105 107
106 final _hasDeferredSupertype = new HashSet<ClassElement>(); 108 final _hasDeferredSupertype = new HashSet<ClassElement>();
107 109
108 final _eagerTopLevelFields = new HashSet<Element>.identity(); 110 final _eagerTopLevelFields = new HashSet<Element>.identity();
109 111
110 /// The type provider from the current Analysis [context]. 112 /// The type provider from the current Analysis [context].
111 final TypeProvider types; 113 final TypeProvider types;
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 _classProperties = new ClassPropertyModel.build(classElem, extensions); 816 _classProperties = new ClassPropertyModel.build(classElem, extensions);
815 817
816 var classExpr = _emitClassExpression( 818 var classExpr = _emitClassExpression(
817 classElem, _emitClassMethods(node, ctors, fields), 819 classElem, _emitClassMethods(node, ctors, fields),
818 fields: allFields); 820 fields: allFields);
819 821
820 var body = <JS.Statement>[]; 822 var body = <JS.Statement>[];
821 _initExtensionSymbols(classElem, methods, fields, body); 823 _initExtensionSymbols(classElem, methods, fields, body);
822 _emitSuperHelperSymbols(_superHelperSymbols, body); 824 _emitSuperHelperSymbols(_superHelperSymbols, body);
823 825
826 var syntheticSuperId = _syntheticSuperclasses[classElem];
827 if (syntheticSuperId != null) {
828 body.add(js.statement('const # = #;', [
829 syntheticSuperId,
830 _emitSyntheticSuperClassExpr(classElem, syntheticSuperId)
831 ]));
832 }
833
824 // Emit the class, e.g. `core.Object = class Object { ... }` 834 // Emit the class, e.g. `core.Object = class Object { ... }`
825 _defineClass(classElem, className, classExpr, isCallable, body); 835 _defineClass(classElem, className, classExpr, isCallable, body);
826 836
827 // Emit things that come after the ES6 `class ... { ... }`. 837 // Emit things that come after the ES6 `class ... { ... }`.
828 var jsPeerNames = _getJSPeerNames(classElem); 838 var jsPeerNames = _getJSPeerNames(classElem);
839 var targetClassName = syntheticSuperId ?? className;
829 JS.Statement deferredBaseClass = 840 JS.Statement deferredBaseClass =
830 _setBaseClass(classElem, className, jsPeerNames, body); 841 _setBaseClass(classElem, targetClassName, className, jsPeerNames, body);
831 842
832 _emitClassTypeTests(classElem, className, body); 843 _emitClassTypeTests(classElem, className, body);
833 844
834 _defineNamedConstructors(ctors, body, className, isCallableTransitive); 845 _defineNamedConstructors(ctors, body, className, isCallableTransitive);
835 _emitVirtualFieldSymbols(className, body); 846 _emitVirtualFieldSymbols(className, body);
847 _emitVirtualizedFieldSymbols(className, body);
836 _emitClassSignature( 848 _emitClassSignature(
837 methods, allFields, classElem, ctors, extensions, className, body); 849 methods, allFields, classElem, ctors, extensions, className, body);
838 _defineExtensionMembers(extensions, className, body); 850 _defineExtensionMembers(extensions, className, body);
839 _emitClassMetadata(node.metadata, className, body); 851 _emitClassMetadata(node.metadata, className, body);
840 852
841 JS.Statement classDef = _statement(body); 853 JS.Statement classDef = _statement(body);
842 854
843 var typeFormals = classElem.typeParameters; 855 var typeFormals = classElem.typeParameters;
844 if (typeFormals.isNotEmpty) { 856 if (typeFormals.isNotEmpty) {
845 classDef = _defineClassTypeArguments( 857 classDef = _defineClassTypeArguments(
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 } 1102 }
1091 1103
1092 void _emitVirtualFieldSymbols( 1104 void _emitVirtualFieldSymbols(
1093 JS.Expression className, List<JS.Statement> body) { 1105 JS.Expression className, List<JS.Statement> body) {
1094 _classProperties.virtualFields.forEach((field, virtualField) { 1106 _classProperties.virtualFields.forEach((field, virtualField) {
1095 body.add(js.statement('const # = Symbol(#.name + "." + #.toString());', 1107 body.add(js.statement('const # = Symbol(#.name + "." + #.toString());',
1096 [virtualField, className, _declareMemberName(field.getter)])); 1108 [virtualField, className, _declareMemberName(field.getter)]));
1097 }); 1109 });
1098 } 1110 }
1099 1111
1112 void _emitVirtualizedFieldSymbols(
1113 JS.Expression className, List<JS.Statement> body) {
1114 _classProperties.virtualizedFields.forEach((field, virtualField) {
1115 body.add(js.statement('const # = #;', [
1116 virtualField,
1117 _callHelper('virtualName(#)', _declareMemberName(field.getter))
1118 ]));
1119 });
1120 }
1121
1100 void _defineClass(ClassElement classElem, JS.Expression className, 1122 void _defineClass(ClassElement classElem, JS.Expression className,
1101 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) { 1123 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) {
1102 JS.Expression callableClass; 1124 JS.Expression callableClass;
1103 if (isCallable && classElem.unnamedConstructor != null) { 1125 if (isCallable && classElem.unnamedConstructor != null) {
1104 callableClass = 1126 callableClass =
1105 _emitCallableClass(classExpr, classElem.unnamedConstructor); 1127 _emitCallableClass(classExpr, classElem.unnamedConstructor);
1106 } 1128 }
1107 1129
1108 if (classElem.typeParameters.isNotEmpty) { 1130 if (classElem.typeParameters.isNotEmpty) {
1109 if (callableClass != null) { 1131 if (callableClass != null) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 var genericInst = _emitType(dynType, lowerGeneric: true); 1249 var genericInst = _emitType(dynType, lowerGeneric: true);
1228 return js.statement( 1250 return js.statement(
1229 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); 1251 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]);
1230 } 1252 }
1231 1253
1232 bool _deferIfNeeded(DartType type, ClassElement current) { 1254 bool _deferIfNeeded(DartType type, ClassElement current) {
1233 if (type is ParameterizedType) { 1255 if (type is ParameterizedType) {
1234 var typeArguments = type.typeArguments; 1256 var typeArguments = type.typeArguments;
1235 for (var typeArg in typeArguments) { 1257 for (var typeArg in typeArguments) {
1236 var typeElement = typeArg.element; 1258 var typeElement = typeArg.element;
1237 // FIXME(vsm): This does not track mutual recursive dependences. 1259 // FIXME(vsm): This does not track mutual recursive dependencies.
1238 if (current == typeElement || _deferIfNeeded(typeArg, current)) { 1260 if (current == typeElement || _deferIfNeeded(typeArg, current)) {
1239 return true; 1261 return true;
1240 } 1262 }
1241 } 1263 }
1242 } 1264 }
1243 return false; 1265 return false;
1244 } 1266 }
1245 1267
1268 JS.Expression _emitSyntheticSuperClassExpr(
1269 ClassElement element, JS.Identifier id) {
1270 var heritage = _emitClassHeritage(element, ignoreSynthetic: true);
1271 var typeParams = _emitTypeFormals(element.typeParameters);
1272 var methods = <JS.Method>[];
1273
1274 // Introduce the new forwarder with one-shot initialization support.
1275 var body = <JS.Statement>[];
1276
1277 var virtualizeArguments = <JS.Expression>[];
1278 for (var field in _classProperties.virtualizedFields.keys) {
1279 JS.TemporaryId fieldId = _classProperties.virtualizedFields[field];
1280 var name = _declareMemberName(field.getter);
1281 virtualizeArguments.add(name);
1282 virtualizeArguments.add(fieldId);
1283 }
1284 body.add(_callHelperStatement(
1285 'virtualize(this, #);', new JS.ArrayInitializer(virtualizeArguments)));
1286 body.add(js.statement('super.new.apply(this, arguments)'));
1287
1288 var constructorName = _propertyName('new');
1289 methods.add(new JS.Method(
1290 constructorName, js.call('function() { #; }', [body]) as JS.Fun));
1291
1292 for (var field in _classProperties.virtualizedFields.keys) {
1293 JS.TemporaryId fieldId = _classProperties.virtualizedFields[field];
1294 var name = _declareMemberName(field.getter);
1295 var getter = js.call('function() { return this[#]; }', [fieldId]);
1296 methods.add(new JS.Method(name, getter, isGetter: true));
1297 var setter = js.call('function(value) { this[#] = value; }', [fieldId]);
1298 methods.add(new JS.Method(name, setter, isSetter: true));
1299 }
1300
1301 return new JS.ClassExpression(id, heritage, methods,
1302 typeParams: typeParams);
1303 }
1304
1246 JS.ClassExpression _emitClassExpression( 1305 JS.ClassExpression _emitClassExpression(
1247 ClassElement element, List<JS.Method> methods, 1306 ClassElement element, List<JS.Method> methods,
1248 {List<FieldDeclaration> fields}) { 1307 {List<FieldDeclaration> fields}) {
1249 String name = element.name; 1308 String name = element.name;
1250 var heritage = _emitClassHeritage(element); 1309 var heritage = _emitClassHeritage(element);
1251 var typeParams = _emitTypeFormals(element.typeParameters); 1310 var typeParams = _emitTypeFormals(element.typeParameters);
1252 var jsFields = fields?.map(_emitTypeScriptField)?.toList(); 1311 var jsFields = fields?.map(_emitTypeScriptField)?.toList();
1253 1312
1254 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods, 1313 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods,
1255 typeParams: typeParams, fields: jsFields); 1314 typeParams: typeParams, fields: jsFields);
1256 } 1315 }
1257 1316
1258 JS.Expression _emitClassHeritage(ClassElement element) { 1317 JS.Expression _emitClassHeritage(ClassElement element,
1318 {bool ignoreSynthetic = false}) {
1259 var type = element.type; 1319 var type = element.type;
1260 if (type.isObject) return null; 1320 if (type.isObject) return null;
1261 1321
1262 _loader.startTopLevel(element); 1322 _loader.startTopLevel(element);
1263 1323
1264 // List of "direct" supertypes (supertype + mixins) 1324 // List of "direct" supertypes (supertype + mixins)
1265 var basetypes = [type.superclass]..addAll(type.mixins); 1325 var basetypes = [type.superclass]..addAll(type.mixins);
1266 1326
1267 // If any of these are recursive (via type parameter), defer setting 1327 // If any of these are recursive (via type parameter), defer setting
1268 // the real superclass. 1328 // the real superclass.
1269 if (basetypes.any((t) => _deferIfNeeded(t, element))) { 1329 if (basetypes.any((t) => _deferIfNeeded(t, element))) {
1270 // Fall back to raw type 1330 // Fall back to raw type
1271 basetypes = 1331 basetypes =
1272 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList(); 1332 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList();
1273 _hasDeferredSupertype.add(element); 1333 _hasDeferredSupertype.add(element);
1274 } 1334 }
1275 1335
1276 // List of "direct" JS superclasses 1336 // List of "direct" JS superclasses
1277 var baseclasses = basetypes 1337 var baseclasses = basetypes
1278 .map((t) => _emitConstructorAccess(t, nameType: false)) 1338 .map((t) => _emitConstructorAccess(t, nameType: false))
1279 .toList(); 1339 .toList();
1280 assert(baseclasses.isNotEmpty); 1340 assert(baseclasses.isNotEmpty);
1341
1342 if (!ignoreSynthetic &&
1343 _classProperties != null &&
1344 _classProperties.virtualizedFields.isNotEmpty) {
1345 // TODO(kasperl): we would want to have a unique generated ID here.
1346 // We can't use 'TemporaryId' since a class is "declared" twice:
1347 // var ClassName = class ClassName { ... }
1348 var id = new JS.Identifier('${element.name}_${basetypes[0].name}');
1349 _syntheticSuperclasses[element] = id;
1350 baseclasses = [id];
1351 }
1352
1281 var heritage = (baseclasses.length == 1) 1353 var heritage = (baseclasses.length == 1)
1282 ? baseclasses.first 1354 ? baseclasses.first
1283 : _callHelper('mixin(#)', [baseclasses]); 1355 : _callHelper('mixin(#)', [baseclasses]);
1284 1356
1285 _loader.finishTopLevel(element); 1357 _loader.finishTopLevel(element);
1286 1358
1287 return heritage; 1359 return heritage;
1288 } 1360 }
1289 1361
1290 /// Provide Dart getters and setters that forward to the underlying native 1362 /// Provide Dart getters and setters that forward to the underlying native
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 1658
1587 /// Emit a getter or setter that simply forwards to the superclass getter or 1659 /// Emit a getter or setter that simply forwards to the superclass getter or
1588 /// setter. This is needed because in ES6, if you only override a getter 1660 /// setter. This is needed because in ES6, if you only override a getter
1589 /// (alternatively, a setter), then there is an implicit override of the 1661 /// (alternatively, a setter), then there is an implicit override of the
1590 /// setter (alternatively, the getter) that does nothing. 1662 /// setter (alternatively, the getter) that does nothing.
1591 JS.Method _emitSuperAccessorWrapper( 1663 JS.Method _emitSuperAccessorWrapper(
1592 MethodDeclaration method, InterfaceType type) { 1664 MethodDeclaration method, InterfaceType type) {
1593 var methodElement = method.element as PropertyAccessorElement; 1665 var methodElement = method.element as PropertyAccessorElement;
1594 var field = methodElement.variable; 1666 var field = methodElement.variable;
1595 if (!field.isSynthetic) return null; 1667 if (!field.isSynthetic) return null;
1668 if (!(field.getter?.isAbstract == false ||
1669 field.setter?.isAbstract == false)) {
1670 return null;
1671 }
1596 1672
1597 // Generate a corresponding virtual getter / setter. 1673 // Generate a corresponding virtual getter / setter.
1598 var name = _declareMemberName(methodElement); 1674 var name = _declareMemberName(methodElement);
1599 if (method.isGetter) { 1675 if (method.isGetter) {
1600 var setter = field.setter; 1676 var setter = field.setter;
1601 if ((setter == null || setter.isAbstract) && 1677 if ((setter == null || setter.isAbstract) &&
1602 _classProperties.inheritedSetters.contains(field.name)) { 1678 _classProperties.inheritedSetters.contains(field.name)) {
1603 // Generate a setter that forwards to super. 1679 // Generate a setter that forwards to super.
1604 var fn = js.call('function(value) { super[#] = value; }', [name]); 1680 var fn = js.call('function(value) { super[#] = value; }', [name]);
1605 return new JS.Method(name, fn, isSetter: true); 1681 return new JS.Method(name, fn, isSetter: true);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { 1755 ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
1680 if (jsPeerName != null) { 1756 if (jsPeerName != null) {
1681 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [ 1757 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [
1682 _runtimeModule, 1758 _runtimeModule,
1683 _propertyName(jsPeerName), 1759 _propertyName(jsPeerName),
1684 _emitTopLevelName(classElem) 1760 _emitTopLevelName(classElem)
1685 ])); 1761 ]));
1686 } 1762 }
1687 } 1763 }
1688 1764
1689 JS.Statement _setBaseClass(ClassElement classElem, JS.Expression className, 1765 /// Sets the baseclass of [classElem], represented by [targetClassName], to
1690 List<String> jsPeerNames, List<JS.Statement> body) { 1766 /// a "corrected" version of the base class.
1767 ///
1768 /// The [targetClassName] and [className] may differ if there is a
1769 /// virtualization class injected in between the [classElem] and its
1770 /// superclass.
1771 JS.Statement _setBaseClass(
1772 ClassElement classElem,
1773 JS.Expression targetClassName,
1774 JS.Expression className,
1775 List<String> jsPeerNames,
1776 List<JS.Statement> body) {
1691 var typeFormals = classElem.typeParameters; 1777 var typeFormals = classElem.typeParameters;
1692 if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) { 1778 if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) {
1693 for (var peer in jsPeerNames) { 1779 for (var peer in jsPeerNames) {
1694 // TODO(jmesserly): we should just extend Array in the first place 1780 // TODO(jmesserly): we should just extend Array in the first place
1695 var newBaseClass = _callHelper('global.#', [peer]); 1781 var newBaseClass = _callHelper('global.#', [peer]);
1696 body.add(_callHelperStatement( 1782 body.add(_callHelperStatement(
1697 'setExtensionBaseClass(#, #);', [className, newBaseClass])); 1783 'setExtensionBaseClass(#, #);', [targetClassName, newBaseClass]));
1698 } 1784 }
1699 } else if (_hasDeferredSupertype.contains(classElem)) { 1785 } else if (_hasDeferredSupertype.contains(classElem)) {
1700 // TODO(vsm): consider just threading the deferred supertype through 1786 // TODO(vsm): consider just threading the deferred supertype through
1701 // instead of recording classElem in a set on the class and recomputing 1787 // instead of recording classElem in a set on the class and recomputing
1702 var newBaseClass = _emitType(classElem.type.superclass, 1788 var newBaseClass = _emitType(classElem.type.superclass,
1703 nameType: false, subClass: classElem, className: className); 1789 nameType: false, subClass: classElem, className: className);
1704 if (classElem.type.mixins.isNotEmpty) { 1790 if (classElem.type.mixins.isNotEmpty) {
1705 var mixins = classElem.type.mixins 1791 var mixins = classElem.type.mixins
1706 .map((t) => _emitType(t, nameType: false)) 1792 .map((t) => _emitType(t, nameType: false))
1707 .toList(); 1793 .toList();
1708 mixins.insert(0, newBaseClass); 1794 mixins.insert(0, newBaseClass);
1709 newBaseClass = _callHelper('mixin(#)', [mixins]); 1795 newBaseClass = _callHelper('mixin(#)', [mixins]);
1710 } 1796 }
1711 var deferredBaseClass = _callHelperStatement( 1797 var deferredBaseClass = _callHelperStatement(
1712 'setBaseClass(#, #);', [className, newBaseClass]); 1798 'setBaseClass(#, #);', [targetClassName, newBaseClass]);
1713 if (typeFormals.isNotEmpty) return deferredBaseClass; 1799 if (typeFormals.isNotEmpty) return deferredBaseClass;
1714 body.add(deferredBaseClass); 1800 body.add(deferredBaseClass);
1715 } 1801 }
1716 return null; 1802 return null;
1717 } 1803 }
1718 1804
1719 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, 1805 void _defineNamedConstructors(List<ConstructorDeclaration> ctors,
1720 List<JS.Statement> body, JS.Expression className, bool isCallable) { 1806 List<JS.Statement> body, JS.Expression className, bool isCallable) {
1721 var code = isCallable 1807 var code = isCallable
1722 ? 'defineNamedConstructorCallable(#, #, #);' 1808 ? 'defineNamedConstructorCallable(#, #, #);'
(...skipping 3250 matching lines...) Expand 10 before | Expand all | Expand 10 after
4973 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', 5059 js.call('(#[#._extensionType]) ? #[#[#]] : #.#',
4974 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) 5060 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name])
4975 ]); 5061 ]);
4976 } 5062 }
4977 return _callHelper('#(#, #)', 5063 return _callHelper('#(#, #)',
4978 [_emitDynamicOperationName('dload'), _visit(target), name]); 5064 [_emitDynamicOperationName('dload'), _visit(target), name]);
4979 } 5065 }
4980 5066
4981 var jsTarget = _emitTarget(target, member, isStatic); 5067 var jsTarget = _emitTarget(target, member, isStatic);
4982 bool isSuper = jsTarget is JS.Super; 5068 bool isSuper = jsTarget is JS.Super;
4983 if (isSuper &&
4984 !member.isSynthetic &&
4985 member is FieldElementImpl &&
4986 !member.isVirtual) {
4987 // If super.x is a sealed field, then x is an instance property since
4988 // subclasses cannot override x.
4989 jsTarget = new JS.This();
4990 }
4991
4992 JS.Expression result; 5069 JS.Expression result;
4993 if (member != null && member is MethodElement && !isStatic) { 5070 if (member != null && member is MethodElement && !isStatic) {
4994 // Tear-off methods: explicitly bind it. 5071 // Tear-off methods: explicitly bind it.
4995 if (isSuper) { 5072 if (isSuper) {
4996 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]); 5073 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]);
4997 } else if (_isObjectMemberCall(target, memberName)) { 5074 } else if (_isObjectMemberCall(target, memberName)) {
4998 result = _callHelper('bind(#, #, #.#)', 5075 result = _callHelper('bind(#, #, #.#)',
4999 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); 5076 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]);
5000 } else { 5077 } else {
5001 result = _callHelper('bind(#, #)', [jsTarget, name]); 5078 result = _callHelper('bind(#, #)', [jsTarget, name]);
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after
5890 if (targetIdentifier.staticElement is! PrefixElement) return false; 5967 if (targetIdentifier.staticElement is! PrefixElement) return false;
5891 var prefix = targetIdentifier.staticElement as PrefixElement; 5968 var prefix = targetIdentifier.staticElement as PrefixElement;
5892 5969
5893 // The library the prefix is referring to must come from a deferred import. 5970 // The library the prefix is referring to must come from a deferred import.
5894 var containingLibrary = resolutionMap 5971 var containingLibrary = resolutionMap
5895 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5972 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5896 .library; 5973 .library;
5897 var imports = containingLibrary.getImportsWithPrefix(prefix); 5974 var imports = containingLibrary.getImportsWithPrefix(prefix);
5898 return imports.length == 1 && imports[0].isDeferred; 5975 return imports.length == 1 && imports[0].isDeferred;
5899 } 5976 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698