| 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 // 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 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
| 6 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
| 7 | 7 |
| 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 860 | 860 |
| 861 if (m.element is PropertyAccessorElement) { | 861 if (m.element is PropertyAccessorElement) { |
| 862 jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses)); | 862 jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses)); |
| 863 } | 863 } |
| 864 | 864 |
| 865 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { | 865 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { |
| 866 hasIterator = true; | 866 hasIterator = true; |
| 867 jsMethods.add(_emitIterable(type)); | 867 jsMethods.add(_emitIterable(type)); |
| 868 } | 868 } |
| 869 } else if (m is FieldDeclaration) { | 869 } else if (m is FieldDeclaration) { |
| 870 if (_extensionTypes.contains(element)) { | 870 if (_extensionTypes.isNativeClass(element)) { |
| 871 jsMethods.addAll(_emitNativeFieldAccessors(m)); | 871 jsMethods.addAll(_emitNativeFieldAccessors(m)); |
| 872 continue; | 872 continue; |
| 873 } | 873 } |
| 874 if (m.isStatic) continue; | 874 if (m.isStatic) continue; |
| 875 for (VariableDeclaration field in m.fields.variables) { | 875 for (VariableDeclaration field in m.fields.variables) { |
| 876 if (virtualFields.containsKey(field.element)) { | 876 if (virtualFields.containsKey(field.element)) { |
| 877 jsMethods.addAll(_emitVirtualFieldAccessor(field, virtualFields)); | 877 jsMethods.addAll(_emitVirtualFieldAccessor(field, virtualFields)); |
| 878 } | 878 } |
| 879 } | 879 } |
| 880 } | 880 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method, | 930 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method, |
| 931 InterfaceType type, List<ClassElement> superclasses) { | 931 InterfaceType type, List<ClassElement> superclasses) { |
| 932 var methodElement = method.element as PropertyAccessorElement; | 932 var methodElement = method.element as PropertyAccessorElement; |
| 933 var field = methodElement.variable; | 933 var field = methodElement.variable; |
| 934 if (!field.isSynthetic) return null; | 934 if (!field.isSynthetic) return null; |
| 935 var propertyOverrideResult = checkForPropertyOverride( | 935 var propertyOverrideResult = checkForPropertyOverride( |
| 936 methodElement.variable, superclasses, _extensionTypes); | 936 methodElement.variable, superclasses, _extensionTypes); |
| 937 | 937 |
| 938 // Generate a corresponding virtual getter / setter. | 938 // Generate a corresponding virtual getter / setter. |
| 939 var name = _elementMemberName(methodElement, | 939 var name = _elementMemberName(methodElement, |
| 940 allowExtensions: _extensionTypes.contains(type.element)); | 940 allowExtensions: _extensionTypes.isNativeClass(type.element)); |
| 941 if (method.isGetter) { | 941 if (method.isGetter) { |
| 942 // Generate a setter | 942 // Generate a setter |
| 943 if (field.setter != null || !propertyOverrideResult.foundSetter) | 943 if (field.setter != null || !propertyOverrideResult.foundSetter) |
| 944 return null; | 944 return null; |
| 945 var fn = js.call('function(value) { super[#] = value; }', [name]); | 945 var fn = js.call('function(value) { super[#] = value; }', [name]); |
| 946 return new JS.Method(name, fn, isSetter: true); | 946 return new JS.Method(name, fn, isSetter: true); |
| 947 } else { | 947 } else { |
| 948 // Generate a getter | 948 // Generate a getter |
| 949 if (field.getter != null || !propertyOverrideResult.foundGetter) | 949 if (field.getter != null || !propertyOverrideResult.foundGetter) |
| 950 return null; | 950 return null; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 | 993 |
| 994 /// Gets the JS peer for this Dart type if any, otherwise null. | 994 /// Gets the JS peer for this Dart type if any, otherwise null. |
| 995 /// | 995 /// |
| 996 /// For example for dart:_interceptors `JSArray` this will return "Array", | 996 /// For example for dart:_interceptors `JSArray` this will return "Array", |
| 997 /// referring to the JavaScript built-in `Array` type. | 997 /// referring to the JavaScript built-in `Array` type. |
| 998 String _getJSPeerName(ClassElement classElem) { | 998 String _getJSPeerName(ClassElement classElem) { |
| 999 var jsPeerName = getAnnotationName( | 999 var jsPeerName = getAnnotationName( |
| 1000 classElem, | 1000 classElem, |
| 1001 (a) => | 1001 (a) => |
| 1002 isJsPeerInterface(a) || | 1002 isJsPeerInterface(a) || |
| 1003 isNativeAnnotation(a) && _extensionTypes.contains(classElem)); | 1003 isNativeAnnotation(a) && _extensionTypes.isNativeClass(classElem)); |
| 1004 if (jsPeerName != null && jsPeerName.contains(',')) { | 1004 if (jsPeerName != null && jsPeerName.contains(',')) { |
| 1005 jsPeerName = jsPeerName.split(',')[0]; | 1005 jsPeerName = jsPeerName.split(',')[0]; |
| 1006 } | 1006 } |
| 1007 return jsPeerName; | 1007 return jsPeerName; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 void _registerExtensionType(ClassElement classElem, List<JS.Statement> body) { | 1010 void _registerExtensionType(ClassElement classElem, List<JS.Statement> body) { |
| 1011 var jsPeerName = _getJSPeerName(classElem); | 1011 var jsPeerName = _getJSPeerName(classElem); |
| 1012 if (jsPeerName != null) { | 1012 if (jsPeerName != null) { |
| 1013 // TODO(jmesserly): this copies the dynamic members. | 1013 // TODO(jmesserly): this copies the dynamic members. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 | 1084 |
| 1085 /// If a concrete class implements one of our extensions, we might need to | 1085 /// If a concrete class implements one of our extensions, we might need to |
| 1086 /// add forwarders. | 1086 /// add forwarders. |
| 1087 void _defineExtensionMembers(List<ExecutableElement> extensions, | 1087 void _defineExtensionMembers(List<ExecutableElement> extensions, |
| 1088 JS.Expression className, List<JS.Statement> body) { | 1088 JS.Expression className, List<JS.Statement> body) { |
| 1089 // If a concrete class implements one of our extensions, we might need to | 1089 // If a concrete class implements one of our extensions, we might need to |
| 1090 // add forwarders. | 1090 // add forwarders. |
| 1091 if (extensions.isNotEmpty) { | 1091 if (extensions.isNotEmpty) { |
| 1092 var methodNames = <JS.Expression>[]; | 1092 var methodNames = <JS.Expression>[]; |
| 1093 for (var e in extensions) { | 1093 for (var e in extensions) { |
| 1094 methodNames.add(_elementMemberName(e)); | 1094 methodNames.add(_elementMemberName(e, allowExtensions: false)); |
| 1095 } | 1095 } |
| 1096 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ | 1096 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ |
| 1097 className, | 1097 className, |
| 1098 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) | 1098 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) |
| 1099 ])); | 1099 ])); |
| 1100 } | 1100 } |
| 1101 } | 1101 } |
| 1102 | 1102 |
| 1103 /// Emit the signature on the class recording the runtime type information | 1103 /// Emit the signature on the class recording the runtime type information |
| 1104 void _emitClassSignature( | 1104 void _emitClassSignature( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1121 var sNames = <JS.Expression>[]; | 1121 var sNames = <JS.Expression>[]; |
| 1122 for (MethodDeclaration node in methods) { | 1122 for (MethodDeclaration node in methods) { |
| 1123 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | 1123 if (!(node.isSetter || node.isGetter || node.isAbstract)) { |
| 1124 var name = node.name.name; | 1124 var name = node.name.name; |
| 1125 var element = node.element; | 1125 var element = node.element; |
| 1126 var inheritedElement = | 1126 var inheritedElement = |
| 1127 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); | 1127 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); |
| 1128 if (inheritedElement != null && inheritedElement.type == element.type) { | 1128 if (inheritedElement != null && inheritedElement.type == element.type) { |
| 1129 continue; | 1129 continue; |
| 1130 } | 1130 } |
| 1131 var memberName = _elementMemberName(element); | 1131 var memberName = _elementMemberName(element, |
| 1132 allowExtensions: _extensionTypes.isNativeClass(classElem)); |
| 1132 var parts = _emitFunctionTypeParts(element.type); | 1133 var parts = _emitFunctionTypeParts(element.type); |
| 1133 var property = | 1134 var property = |
| 1134 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 1135 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
| 1135 if (node.isStatic) { | 1136 if (node.isStatic) { |
| 1136 tStatics.add(property); | 1137 tStatics.add(property); |
| 1137 sNames.add(memberName); | 1138 sNames.add(memberName); |
| 1138 } else { | 1139 } else { |
| 1139 tMethods.add(property); | 1140 tMethods.add(property); |
| 1140 } | 1141 } |
| 1141 } | 1142 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); | 1174 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); |
| 1174 } | 1175 } |
| 1175 } | 1176 } |
| 1176 | 1177 |
| 1177 /// Ensure `dartx.` symbols we will use are present. | 1178 /// Ensure `dartx.` symbols we will use are present. |
| 1178 void _initExtensionSymbols( | 1179 void _initExtensionSymbols( |
| 1179 ClassElement classElem, | 1180 ClassElement classElem, |
| 1180 List<MethodDeclaration> methods, | 1181 List<MethodDeclaration> methods, |
| 1181 List<FieldDeclaration> fields, | 1182 List<FieldDeclaration> fields, |
| 1182 List<JS.Statement> body) { | 1183 List<JS.Statement> body) { |
| 1183 if (_extensionTypes.contains(classElem)) { | 1184 if (_extensionTypes.hasNativeSubtype(classElem.type)) { |
| 1184 var dartxNames = <JS.Expression>[]; | 1185 var dartxNames = <JS.Expression>[]; |
| 1185 for (var m in methods) { | 1186 for (var m in methods) { |
| 1186 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 1187 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { |
| 1187 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); | 1188 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); |
| 1188 } | 1189 } |
| 1189 } | 1190 } |
| 1190 for (var f in fields) { | 1191 for (var f in fields) { |
| 1191 if (!f.isStatic) { | 1192 if (!f.isStatic) { |
| 1192 for (var d in f.fields.variables) { | 1193 for (var d in f.fields.variables) { |
| 1193 if (d.element.isPublic) { | 1194 if (d.element.isPublic) { |
| 1194 dartxNames.add( | 1195 dartxNames.add( |
| 1195 _elementMemberName(d.element.getter, allowExtensions: false)); | 1196 _elementMemberName(d.element.getter, allowExtensions: false)); |
| 1196 } | 1197 } |
| 1197 } | 1198 } |
| 1198 } | 1199 } |
| 1199 } | 1200 } |
| 1200 if (dartxNames.isNotEmpty) { | 1201 if (dartxNames.isNotEmpty) { |
| 1201 body.add(js.statement('dart.defineExtensionNames(#)', | 1202 body.add(js.statement('dart.defineExtensionNames(#)', |
| 1202 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | 1203 [new JS.ArrayInitializer(dartxNames, multiline: true)])); |
| 1203 } | 1204 } |
| 1204 } | 1205 } |
| 1205 } | 1206 } |
| 1206 | 1207 |
| 1207 List<ExecutableElement> _extensionsToImplement(ClassElement element) { | 1208 List<ExecutableElement> _extensionsToImplement(ClassElement element) { |
| 1208 var members = <ExecutableElement>[]; | 1209 var members = <ExecutableElement>[]; |
| 1209 if (_extensionTypes.contains(element)) return members; | 1210 if (_extensionTypes.isNativeClass(element)) return members; |
| 1210 | 1211 |
| 1211 // Collect all extension types we implement. | 1212 // Collect all extension types we implement. |
| 1212 var type = element.type; | 1213 var type = element.type; |
| 1213 var types = new Set<ClassElement>(); | 1214 var types = _extensionTypes.collectNativeInterfaces(element); |
| 1214 _collectExtensions(type, types); | |
| 1215 if (types.isEmpty) return members; | 1215 if (types.isEmpty) return members; |
| 1216 | 1216 |
| 1217 // Collect all possible extension method names. | 1217 // Collect all possible extension method names. |
| 1218 var extensionMembers = new HashSet<String>(); | 1218 var extensionMembers = new HashSet<String>(); |
| 1219 for (var t in types) { | 1219 for (var t in types) { |
| 1220 for (var m in [t.methods, t.accessors].expand((e) => e)) { | 1220 for (var m in [t.methods, t.accessors].expand((e) => e)) { |
| 1221 if (!m.isStatic) extensionMembers.add(m.name); | 1221 if (!m.isStatic) extensionMembers.add(m.name); |
| 1222 } | 1222 } |
| 1223 } | 1223 } |
| 1224 | 1224 |
| 1225 // Collect all of extension methods this type implements. | 1225 // Collect all of extension methods this type implements. |
| 1226 for (var m in [type.methods, type.accessors].expand((e) => e)) { | 1226 for (var m in [type.methods, type.accessors].expand((e) => e)) { |
| 1227 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) { | 1227 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) { |
| 1228 members.add(m); | 1228 members.add(m); |
| 1229 } | 1229 } |
| 1230 } | 1230 } |
| 1231 return members; | 1231 return members; |
| 1232 } | 1232 } |
| 1233 | 1233 |
| 1234 /// Collections the type and all supertypes, including interfaces, but | |
| 1235 /// excluding [Object]. | |
| 1236 void _collectExtensions(InterfaceType type, Set<ClassElement> types) { | |
| 1237 if (type.isObject) return; | |
| 1238 var element = type.element; | |
| 1239 if (_extensionTypes.contains(element)) types.add(element); | |
| 1240 for (var m in type.mixins.reversed) { | |
| 1241 _collectExtensions(m, types); | |
| 1242 } | |
| 1243 for (var i in type.interfaces) { | |
| 1244 _collectExtensions(i, types); | |
| 1245 } | |
| 1246 _collectExtensions(type.superclass, types); | |
| 1247 } | |
| 1248 | |
| 1249 /// Generates the implicit default constructor for class C of the form | 1234 /// Generates the implicit default constructor for class C of the form |
| 1250 /// `C() : super() {}`. | 1235 /// `C() : super() {}`. |
| 1251 JS.Method _emitImplicitConstructor( | 1236 JS.Method _emitImplicitConstructor( |
| 1252 ClassDeclaration node, | 1237 ClassDeclaration node, |
| 1253 List<FieldDeclaration> fields, | 1238 List<FieldDeclaration> fields, |
| 1254 Map<FieldElement, JS.TemporaryId> virtualFields) { | 1239 Map<FieldElement, JS.TemporaryId> virtualFields) { |
| 1255 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); | 1240 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); |
| 1256 | 1241 |
| 1257 // If we don't have a method body, skip this. | 1242 // If we don't have a method body, skip this. |
| 1258 var superCall = _superConstructorCall(node.element); | 1243 var superCall = _superConstructorCall(node.element); |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 fn.params.isNotEmpty) { | 1643 fn.params.isNotEmpty) { |
| 1659 // []= methods need to return the value. We could also address this at | 1644 // []= methods need to return the value. We could also address this at |
| 1660 // call sites, but it's cleaner to instead transform the operator method
. | 1645 // call sites, but it's cleaner to instead transform the operator method
. |
| 1661 fn = _alwaysReturnLastParameter(fn); | 1646 fn = _alwaysReturnLastParameter(fn); |
| 1662 } | 1647 } |
| 1663 | 1648 |
| 1664 fn = _makeGenericFunction(fn); | 1649 fn = _makeGenericFunction(fn); |
| 1665 } | 1650 } |
| 1666 | 1651 |
| 1667 return annotate( | 1652 return annotate( |
| 1668 new JS.Method(_elementMemberName(node.element), fn, | 1653 new JS.Method( |
| 1654 _elementMemberName(node.element, |
| 1655 allowExtensions: _extensionTypes.isNativeClass(type.element)), |
| 1656 fn, |
| 1669 isGetter: node.isGetter, | 1657 isGetter: node.isGetter, |
| 1670 isSetter: node.isSetter, | 1658 isSetter: node.isSetter, |
| 1671 isStatic: node.isStatic), | 1659 isStatic: node.isStatic), |
| 1672 node, | 1660 node, |
| 1673 node.element); | 1661 node.element); |
| 1674 } | 1662 } |
| 1675 | 1663 |
| 1676 /// Transform the function so the last parameter is always returned. | 1664 /// Transform the function so the last parameter is always returned. |
| 1677 /// | 1665 /// |
| 1678 /// This is useful for indexed set methods, which otherwise would not have | 1666 /// This is useful for indexed set methods, which otherwise would not have |
| (...skipping 1855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3534 // Is this a member on `Object`? | 3522 // Is this a member on `Object`? |
| 3535 if (!isObjectProperty(memberName)) { | 3523 if (!isObjectProperty(memberName)) { |
| 3536 return false; | 3524 return false; |
| 3537 } | 3525 } |
| 3538 | 3526 |
| 3539 // Check if the target could be `null`, is dynamic, or may be an extension | 3527 // Check if the target could be `null`, is dynamic, or may be an extension |
| 3540 // native type. In all of those cases we need defensive code generation. | 3528 // native type. In all of those cases we need defensive code generation. |
| 3541 var type = getStaticType(target); | 3529 var type = getStaticType(target); |
| 3542 return isNullable(target) || | 3530 return isNullable(target) || |
| 3543 type.isDynamic || | 3531 type.isDynamic || |
| 3544 (_extensionTypes.contains(type.element) && target is! SuperExpression); | 3532 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression); |
| 3545 } | 3533 } |
| 3546 | 3534 |
| 3547 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 3535 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
| 3548 JS.Expression _emitAccess( | 3536 JS.Expression _emitAccess( |
| 3549 Expression target, SimpleIdentifier memberId, DartType resultType) { | 3537 Expression target, SimpleIdentifier memberId, DartType resultType) { |
| 3550 Element member = memberId.staticElement; | 3538 Element member = memberId.staticElement; |
| 3551 if (member is PropertyAccessorElement) { | 3539 if (member is PropertyAccessorElement) { |
| 3552 member = (member as PropertyAccessorElement).variable; | 3540 member = (member as PropertyAccessorElement).variable; |
| 3553 } | 3541 } |
| 3554 bool isStatic = member is ClassMemberElement && member.isStatic; | 3542 bool isStatic = member is ClassMemberElement && member.isStatic; |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4137 name = '+$name'; | 4125 name = '+$name'; |
| 4138 } | 4126 } |
| 4139 | 4127 |
| 4140 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. | 4128 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. |
| 4141 var baseType = type; | 4129 var baseType = type; |
| 4142 while (baseType is TypeParameterType) { | 4130 while (baseType is TypeParameterType) { |
| 4143 baseType = baseType.element.bound; | 4131 baseType = baseType.element.bound; |
| 4144 } | 4132 } |
| 4145 if (allowExtensions && | 4133 if (allowExtensions && |
| 4146 baseType != null && | 4134 baseType != null && |
| 4147 _extensionTypes.contains(baseType.element) && | 4135 _extensionTypes.hasNativeSubtype(baseType) && |
| 4148 !isObjectProperty(name)) { | 4136 !isObjectProperty(name)) { |
| 4149 return js.call('dartx.#', _propertyName(name)); | 4137 return js.call('dartx.#', _propertyName(name)); |
| 4150 } | 4138 } |
| 4151 | 4139 |
| 4152 return _propertyName(name); | 4140 return _propertyName(name); |
| 4153 } | 4141 } |
| 4154 | 4142 |
| 4155 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { | 4143 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { |
| 4156 return _privateNames | 4144 return _privateNames |
| 4157 .putIfAbsent(library, () => new HashMap()) | 4145 .putIfAbsent(library, () => new HashMap()) |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4299 } | 4287 } |
| 4300 | 4288 |
| 4301 bool isLibraryPrefix(Expression node) => | 4289 bool isLibraryPrefix(Expression node) => |
| 4302 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4290 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 4303 | 4291 |
| 4304 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4292 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 4305 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4293 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 4306 | 4294 |
| 4307 bool _isDartRuntime(LibraryElement l) => | 4295 bool _isDartRuntime(LibraryElement l) => |
| 4308 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4296 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |