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

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

Issue 2430953006: fix #27532, implementing a native type with fields (Closed)
Patch Set: Created 4 years, 2 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 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 className = new JS.Identifier(classElem.name); 731 className = new JS.Identifier(classElem.name);
732 } else { 732 } else {
733 className = _emitTopLevelName(classElem); 733 className = _emitTopLevelName(classElem);
734 } 734 }
735 735
736 var allFields = fields.toList()..addAll(staticFields); 736 var allFields = fields.toList()..addAll(staticFields);
737 var superclasses = getSuperclasses(classElem); 737 var superclasses = getSuperclasses(classElem);
738 var virtualFields = <FieldElement, JS.TemporaryId>{}; 738 var virtualFields = <FieldElement, JS.TemporaryId>{};
739 var virtualFieldSymbols = <JS.Statement>[]; 739 var virtualFieldSymbols = <JS.Statement>[];
740 var staticFieldOverrides = new HashSet<FieldElement>(); 740 var staticFieldOverrides = new HashSet<FieldElement>();
741 var extensions = _extensionsToImplement(classElem);
741 _registerPropertyOverrides(classElem, className, superclasses, allFields, 742 _registerPropertyOverrides(classElem, className, superclasses, allFields,
742 virtualFields, virtualFieldSymbols, staticFieldOverrides); 743 virtualFields, virtualFieldSymbols, staticFieldOverrides, extensions);
743 744
744 var classExpr = _emitClassExpression(classElem, 745 var classExpr = _emitClassExpression(classElem,
745 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), 746 _emitClassMethods(node, ctors, fields, superclasses, virtualFields),
746 fields: allFields); 747 fields: allFields);
747 748
748 var body = <JS.Statement>[]; 749 var body = <JS.Statement>[];
749 var extensions = _extensionsToImplement(classElem);
750 _initExtensionSymbols(classElem, methods, fields, body); 750 _initExtensionSymbols(classElem, methods, fields, body);
751 _emitSuperHelperSymbols(_superHelperSymbols, body); 751 _emitSuperHelperSymbols(_superHelperSymbols, body);
752 752
753 // Emit the class, e.g. `core.Object = class Object { ... }` 753 // Emit the class, e.g. `core.Object = class Object { ... }`
754 _defineClass(classElem, className, classExpr, isCallable, body); 754 _defineClass(classElem, className, classExpr, isCallable, body);
755 755
756 // Emit things that come after the ES6 `class ... { ... }`. 756 // Emit things that come after the ES6 `class ... { ... }`.
757 var jsPeerNames = _getJSPeerNames(classElem); 757 var jsPeerNames = _getJSPeerNames(classElem);
758 _setBaseClass(classElem, className, jsPeerNames, body); 758 _setBaseClass(classElem, className, jsPeerNames, body);
759 759
760 _emitClassTypeTests(classElem, className, body); 760 _emitClassTypeTests(classElem, className, body);
761 761
762 _defineNamedConstructors(ctors, body, className, isCallable); 762 _defineNamedConstructors(ctors, body, className, isCallable);
763 _emitVirtualFieldSymbols(virtualFieldSymbols, body); 763 body.addAll(virtualFieldSymbols);
764 _emitClassSignature( 764 _emitClassSignature(
765 methods, allFields, classElem, ctors, extensions, className, body); 765 methods, allFields, classElem, ctors, extensions, className, body);
766 _defineExtensionMembers(extensions, className, body); 766 _defineExtensionMembers(extensions, className, body);
767 _emitClassMetadata(node.metadata, className, body); 767 _emitClassMetadata(node.metadata, className, body);
768 768
769 JS.Statement classDef = _statement(body); 769 JS.Statement classDef = _statement(body);
770 var typeFormals = classElem.typeParameters; 770 var typeFormals = classElem.typeParameters;
771 if (typeFormals.isNotEmpty) { 771 if (typeFormals.isNotEmpty) {
772 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); 772 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef);
773 } 773 }
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 superHelperSymbols.clear(); 994 superHelperSymbols.clear();
995 } 995 }
996 996
997 void _registerPropertyOverrides( 997 void _registerPropertyOverrides(
998 ClassElement classElem, 998 ClassElement classElem,
999 JS.Expression className, 999 JS.Expression className,
1000 List<ClassElement> superclasses, 1000 List<ClassElement> superclasses,
1001 List<FieldDeclaration> fields, 1001 List<FieldDeclaration> fields,
1002 Map<FieldElement, JS.TemporaryId> virtualFields, 1002 Map<FieldElement, JS.TemporaryId> virtualFields,
1003 List<JS.Statement> virtualFieldSymbols, 1003 List<JS.Statement> virtualFieldSymbols,
1004 Set<FieldElement> staticFieldOverrides) { 1004 Set<FieldElement> staticFieldOverrides,
1005 Iterable<ExecutableElement> extensionMembers) {
1006 var extensionNames =
1007 new HashSet<String>.from(extensionMembers.map((e) => e.name));
1005 for (var field in fields) { 1008 for (var field in fields) {
1006 for (VariableDeclaration field in field.fields.variables) { 1009 for (VariableDeclaration fieldDecl in field.fields.variables) {
1007 var overrideInfo = 1010 var field = fieldDecl.element as FieldElement;
1008 checkForPropertyOverride(field.element, superclasses); 1011 var overrideInfo = checkForPropertyOverride(field, superclasses);
1009 if (overrideInfo.foundGetter || overrideInfo.foundSetter) { 1012 if (overrideInfo.foundGetter ||
1010 if (field.element.isStatic) { 1013 overrideInfo.foundSetter ||
1011 staticFieldOverrides.add(field.element); 1014 extensionNames.contains(field.name)) {
1015 if (field.isStatic) {
1016 staticFieldOverrides.add(field);
1012 } else { 1017 } else {
1013 var fieldName = 1018 var virtualField = new JS.TemporaryId(field.name);
1014 _emitMemberName(field.element.name, type: classElem.type); 1019 virtualFields[field] = virtualField;
1015 var virtualField = new JS.TemporaryId(field.element.name);
1016 virtualFields[field.element] = virtualField;
1017 virtualFieldSymbols.add(js.statement( 1020 virtualFieldSymbols.add(js.statement(
1018 'const # = Symbol(#.name + "." + #.toString());', 1021 'const # = Symbol(#.name + "." + #.toString());',
1019 [virtualField, className, fieldName])); 1022 [virtualField, className, _declareMemberName(field.getter)]));
1020 } 1023 }
1021 } 1024 }
1022 } 1025 }
1023 } 1026 }
1024 } 1027 }
1025 1028
1026 void _defineClass(ClassElement classElem, JS.Expression className, 1029 void _defineClass(ClassElement classElem, JS.Expression className,
1027 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) { 1030 JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) {
1028 JS.Expression callableClass; 1031 JS.Expression callableClass;
1029 if (isCallable && classElem.unnamedConstructor != null) { 1032 if (isCallable && classElem.unnamedConstructor != null) {
1030 callableClass = 1033 callableClass =
1031 _emitCallableClass(classExpr, classElem.unnamedConstructor); 1034 _emitCallableClass(classExpr, classElem.unnamedConstructor);
1032 } 1035 }
1033 1036
1034 if (classElem.typeParameters.isNotEmpty) { 1037 if (classElem.typeParameters.isNotEmpty) {
1035 if (callableClass != null) { 1038 if (callableClass != null) {
1036 body.add(js.statement('const # = #;', [classExpr.name, callableClass])); 1039 body.add(js.statement('const # = #;', [classExpr.name, callableClass]));
1037 } else { 1040 } else {
1038 body.add(new JS.ClassDeclaration(classExpr)); 1041 body.add(new JS.ClassDeclaration(classExpr));
1039 } 1042 }
1040 } else { 1043 } else {
1041 body.add(js.statement('# = #;', [className, callableClass ?? classExpr])); 1044 body.add(js.statement('# = #;', [className, callableClass ?? classExpr]));
1042 } 1045 }
1043 } 1046 }
1044 1047
1045 void _emitVirtualFieldSymbols(
1046 List<JS.Statement> virtualFields, List<JS.Statement> body) {
1047 body.addAll(virtualFields);
1048 }
1049
1050 List<JS.Identifier> _emitTypeFormals(List<TypeParameterElement> typeFormals) { 1048 List<JS.Identifier> _emitTypeFormals(List<TypeParameterElement> typeFormals) {
1051 return typeFormals 1049 return typeFormals
1052 .map((t) => new JS.Identifier(t.name)) 1050 .map((t) => new JS.Identifier(t.name))
1053 .toList(growable: false); 1051 .toList(growable: false);
1054 } 1052 }
1055 1053
1056 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED 1054 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED
1057 /// (e.g. `class Foo { i: string; }`) 1055 /// (e.g. `class Foo { i: string; }`)
1058 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) { 1056 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) {
1059 return new JS.VariableDeclarationList( 1057 return new JS.VariableDeclarationList(
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 // Alternatively, perhaps it could be meta-programmed directly in 1205 // Alternatively, perhaps it could be meta-programmed directly in
1208 // dart.registerExtensions? 1206 // dart.registerExtensions?
1209 var jsMethods = <JS.Method>[]; 1207 var jsMethods = <JS.Method>[];
1210 if (!node.isStatic) { 1208 if (!node.isStatic) {
1211 for (var decl in node.fields.variables) { 1209 for (var decl in node.fields.variables) {
1212 var field = decl.element as FieldElement; 1210 var field = decl.element as FieldElement;
1213 var name = getAnnotationName(field, isJsName) ?? field.name; 1211 var name = getAnnotationName(field, isJsName) ?? field.name;
1214 // Generate getter 1212 // Generate getter
1215 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name])); 1213 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name]));
1216 var method = 1214 var method =
1217 new JS.Method(_elementMemberName(field.getter), fn, isGetter: true); 1215 new JS.Method(_declareMemberName(field.getter), fn, isGetter: true);
1218 jsMethods.add(method); 1216 jsMethods.add(method);
1219 1217
1220 // Generate setter 1218 // Generate setter
1221 if (!decl.isFinal) { 1219 if (!decl.isFinal) {
1222 var value = new JS.TemporaryId('value'); 1220 var value = new JS.TemporaryId('value');
1223 fn = new JS.Fun( 1221 fn = new JS.Fun(
1224 [value], js.statement('{ this.# = #; }', [name, value])); 1222 [value], js.statement('{ this.# = #; }', [name, value]));
1225 method = new JS.Method(_elementMemberName(field.setter), fn, 1223 method = new JS.Method(_declareMemberName(field.setter), fn,
1226 isSetter: true); 1224 isSetter: true);
1227 jsMethods.add(method); 1225 jsMethods.add(method);
1228 } 1226 }
1229 } 1227 }
1230 } 1228 }
1231 return jsMethods; 1229 return jsMethods;
1232 } 1230 }
1233 1231
1234 List<JS.Method> _emitClassMethods( 1232 List<JS.Method> _emitClassMethods(
1235 ClassDeclaration node, 1233 ClassDeclaration node,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 } else if (property.isSetter) { 1425 } else if (property.isSetter) {
1428 addProperty('isSetter', js.boolean(true)); 1426 addProperty('isSetter', js.boolean(true));
1429 1427
1430 fnArgs.add(args); 1428 fnArgs.add(args);
1431 positionalArgs = new JS.ArrayInitializer([args]); 1429 positionalArgs = new JS.ArrayInitializer([args]);
1432 } 1430 }
1433 } 1431 }
1434 1432
1435 var fnBody = 1433 var fnBody =
1436 js.call('this.noSuchMethod(new dart.InvocationImpl(#, #, #))', [ 1434 js.call('this.noSuchMethod(new dart.InvocationImpl(#, #, #))', [
1437 _elementMemberName(method), 1435 _declareMemberName(method),
1438 positionalArgs, 1436 positionalArgs,
1439 new JS.ObjectInitializer(invocationProps) 1437 new JS.ObjectInitializer(invocationProps)
1440 ]); 1438 ]);
1441 1439
1442 if (!method.returnType.isDynamic) { 1440 if (!method.returnType.isDynamic) {
1443 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); 1441 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]);
1444 } 1442 }
1445 1443
1446 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), 1444 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]),
1447 typeParams: _emitTypeFormals(method.type.typeFormals)); 1445 typeParams: _emitTypeFormals(method.type.typeFormals));
1448 1446
1449 // TODO(jmesserly): generic type arguments will get dropped. 1447 // TODO(jmesserly): generic type arguments will get dropped.
1450 // We have a similar issue with `dgsend` helpers. 1448 // We have a similar issue with `dgsend` helpers.
1451 return new JS.Method( 1449 return new JS.Method(
1452 _elementMemberName(method, 1450 _declareMemberName(method,
1453 useExtension: 1451 useExtension:
1454 _extensionTypes.isNativeClass(method.enclosingElement)), 1452 _extensionTypes.isNativeClass(method.enclosingElement)),
1455 _makeGenericFunction(fn), 1453 _makeGenericFunction(fn),
1456 isGetter: method is PropertyAccessorElement && method.isGetter, 1454 isGetter: method is PropertyAccessorElement && method.isGetter,
1457 isSetter: method is PropertyAccessorElement && method.isSetter, 1455 isSetter: method is PropertyAccessorElement && method.isSetter,
1458 isStatic: false); 1456 isStatic: false);
1459 } 1457 }
1460 1458
1461 /// Return `true` if the given [classElement] has a noSuchMethod() method 1459 /// Return `true` if the given [classElement] has a noSuchMethod() method
1462 /// distinct from the one declared in class Object, as per the Dart Language 1460 /// distinct from the one declared in class Object, as per the Dart Language
(...skipping 12 matching lines...) Expand all
1475 /// shadowing a field or getter/setter pair on its parent. 1473 /// shadowing a field or getter/setter pair on its parent.
1476 /// 1474 ///
1477 /// This is important because otherwise, trying to read or write the field 1475 /// This is important because otherwise, trying to read or write the field
1478 /// would end up calling the getter or setter, and one of those might not even 1476 /// would end up calling the getter or setter, and one of those might not even
1479 /// exist, resulting in a runtime error. Even if they did exist, that's the 1477 /// exist, resulting in a runtime error. Even if they did exist, that's the
1480 /// wrong behavior if a new field was declared. 1478 /// wrong behavior if a new field was declared.
1481 List<JS.Method> _emitVirtualFieldAccessor(VariableDeclaration field, 1479 List<JS.Method> _emitVirtualFieldAccessor(VariableDeclaration field,
1482 Map<FieldElement, JS.TemporaryId> virtualFields) { 1480 Map<FieldElement, JS.TemporaryId> virtualFields) {
1483 var virtualField = virtualFields[field.element]; 1481 var virtualField = virtualFields[field.element];
1484 var result = <JS.Method>[]; 1482 var result = <JS.Method>[];
1485 var name = _emitMemberName(field.element.name, 1483 var name = _declareMemberName((field.element as FieldElement).getter);
1486 type: (field.element.enclosingElement as ClassElement).type);
1487 var getter = js.call('function() { return this[#]; }', [virtualField]); 1484 var getter = js.call('function() { return this[#]; }', [virtualField]);
1488 result.add(new JS.Method(name, getter, isGetter: true)); 1485 result.add(new JS.Method(name, getter, isGetter: true));
1489 1486
1490 if (field.isFinal) { 1487 if (field.isFinal) {
1491 var setter = js.call('function(value) { super[#] = value; }', [name]); 1488 var setter = js.call('function(value) { super[#] = value; }', [name]);
1492 result.add(new JS.Method(name, setter, isSetter: true)); 1489 result.add(new JS.Method(name, setter, isSetter: true));
1493 } else { 1490 } else {
1494 var setter = 1491 var setter =
1495 js.call('function(value) { this[#] = value; }', [virtualField]); 1492 js.call('function(value) { this[#] = value; }', [virtualField]);
1496 result.add(new JS.Method(name, setter, isSetter: true)); 1493 result.add(new JS.Method(name, setter, isSetter: true));
1497 } 1494 }
1498 1495
1499 return result; 1496 return result;
1500 } 1497 }
1501 1498
1502 /// Emit a getter or setter that simply forwards to the superclass getter or 1499 /// Emit a getter or setter that simply forwards to the superclass getter or
1503 /// setter. This is needed because in ES6, if you only override a getter 1500 /// setter. This is needed because in ES6, if you only override a getter
1504 /// (alternatively, a setter), then there is an implicit override of the 1501 /// (alternatively, a setter), then there is an implicit override of the
1505 /// setter (alternatively, the getter) that does nothing. 1502 /// setter (alternatively, the getter) that does nothing.
1506 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method, 1503 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method,
1507 InterfaceType type, List<ClassElement> superclasses) { 1504 InterfaceType type, List<ClassElement> superclasses) {
1508 var methodElement = method.element as PropertyAccessorElement; 1505 var methodElement = method.element as PropertyAccessorElement;
1509 var field = methodElement.variable; 1506 var field = methodElement.variable;
1510 if (!field.isSynthetic) return null; 1507 if (!field.isSynthetic) return null;
1511 var propertyOverrideResult = 1508 var propertyOverrideResult =
1512 checkForPropertyOverride(methodElement.variable, superclasses); 1509 checkForPropertyOverride(methodElement.variable, superclasses);
1513 1510
1514 // Generate a corresponding virtual getter / setter. 1511 // Generate a corresponding virtual getter / setter.
1515 var name = _elementMemberName(methodElement, 1512 var name = _declareMemberName(methodElement);
1516 useExtension: _extensionTypes.isNativeClass(type.element));
1517 if (method.isGetter) { 1513 if (method.isGetter) {
1518 // Generate a setter 1514 // Generate a setter
1519 if (field.setter != null || !propertyOverrideResult.foundSetter) 1515 if (field.setter != null || !propertyOverrideResult.foundSetter)
1520 return null; 1516 return null;
1521 var fn = js.call('function(value) { super[#] = value; }', [name]); 1517 var fn = js.call('function(value) { super[#] = value; }', [name]);
1522 return new JS.Method(name, fn, isSetter: true); 1518 return new JS.Method(name, fn, isSetter: true);
1523 } else { 1519 } else {
1524 // Generate a getter 1520 // Generate a getter
1525 if (field.getter != null || !propertyOverrideResult.foundGetter) 1521 if (field.getter != null || !propertyOverrideResult.foundGetter)
1526 return null; 1522 return null;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1669 1665
1670 /// If a concrete class implements one of our extensions, we might need to 1666 /// If a concrete class implements one of our extensions, we might need to
1671 /// add forwarders. 1667 /// add forwarders.
1672 void _defineExtensionMembers(List<ExecutableElement> extensions, 1668 void _defineExtensionMembers(List<ExecutableElement> extensions,
1673 JS.Expression className, List<JS.Statement> body) { 1669 JS.Expression className, List<JS.Statement> body) {
1674 // If a concrete class implements one of our extensions, we might need to 1670 // If a concrete class implements one of our extensions, we might need to
1675 // add forwarders. 1671 // add forwarders.
1676 if (extensions.isNotEmpty) { 1672 if (extensions.isNotEmpty) {
1677 var methodNames = <JS.Expression>[]; 1673 var methodNames = <JS.Expression>[];
1678 for (var e in extensions) { 1674 for (var e in extensions) {
1679 methodNames.add(_elementMemberName(e, useExtension: false)); 1675 methodNames.add(_declareMemberName(e, useExtension: false));
1680 } 1676 }
1681 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ 1677 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
1682 className, 1678 className,
1683 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) 1679 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
1684 ])); 1680 ]));
1685 } 1681 }
1686 } 1682 }
1687 1683
1688 /// Emit the signature on the class recording the runtime type information 1684 /// Emit the signature on the class recording the runtime type information
1689 void _emitClassSignature( 1685 void _emitClassSignature(
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 type = _emitAnnotatedFunctionType(element.type, node.metadata, 1731 type = _emitAnnotatedFunctionType(element.type, node.metadata,
1736 parameters: node.parameters?.parameters, 1732 parameters: node.parameters?.parameters,
1737 nameType: options.hoistSignatureTypes, 1733 nameType: options.hoistSignatureTypes,
1738 hoistType: options.hoistSignatureTypes, 1734 hoistType: options.hoistSignatureTypes,
1739 definite: true); 1735 definite: true);
1740 1736
1741 var inheritedElement = lookup(name, currentLibrary); 1737 var inheritedElement = lookup(name, currentLibrary);
1742 if (inheritedElement != null && inheritedElement.type == element.type) { 1738 if (inheritedElement != null && inheritedElement.type == element.type) {
1743 continue; 1739 continue;
1744 } 1740 }
1745 var memberName = _elementMemberName(element, 1741 var memberName = _declareMemberName(element);
1746 useExtension: _extensionTypes.isNativeClass(classElem));
1747 var property = new JS.Property(memberName, type); 1742 var property = new JS.Property(memberName, type);
1748 tMember.add(property); 1743 tMember.add(property);
1749 // TODO(vsm): Why do we need this? 1744 // TODO(vsm): Why do we need this?
1750 if (node.isStatic && !node.isGetter && !node.isSetter) { 1745 if (node.isStatic && !node.isGetter && !node.isSetter) {
1751 sNames.add(memberName); 1746 sNames.add(memberName);
1752 } 1747 }
1753 } 1748 }
1754 1749
1755 var tInstanceFields = <JS.Property>[]; 1750 var tInstanceFields = <JS.Property>[];
1756 var tStaticFields = <JS.Property>[]; 1751 var tStaticFields = <JS.Property>[];
1757 for (FieldDeclaration node in fields) { 1752 for (FieldDeclaration node in fields) {
1758 for (VariableDeclaration field in node.fields.variables) { 1753 for (VariableDeclaration field in node.fields.variables) {
1759 var element = field.element as FieldElement; 1754 var element = field.element as FieldElement;
1760 var memberName = _elementMemberName(element.getter, 1755 var memberName = _declareMemberName(element.getter);
1761 useExtension: _extensionTypes.isNativeClass(classElem));
1762 var type = _emitAnnotatedType(element.type, node.metadata); 1756 var type = _emitAnnotatedType(element.type, node.metadata);
1763 var property = new JS.Property(memberName, type); 1757 var property = new JS.Property(memberName, type);
1764 (node.isStatic ? tStaticFields : tInstanceFields).add(property); 1758 (node.isStatic ? tStaticFields : tInstanceFields).add(property);
1765 } 1759 }
1766 } 1760 }
1767 1761
1768 var tCtors = <JS.Property>[]; 1762 var tCtors = <JS.Property>[];
1769 for (ConstructorDeclaration node in ctors) { 1763 for (ConstructorDeclaration node in ctors) {
1770 var memberName = _constructorName(node.element); 1764 var memberName = _constructorName(node.element);
1771 var element = node.element; 1765 var element = node.element;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1834 /// Ensure `dartx.` symbols we will use are present. 1828 /// Ensure `dartx.` symbols we will use are present.
1835 void _initExtensionSymbols( 1829 void _initExtensionSymbols(
1836 ClassElement classElem, 1830 ClassElement classElem,
1837 List<MethodDeclaration> methods, 1831 List<MethodDeclaration> methods,
1838 List<FieldDeclaration> fields, 1832 List<FieldDeclaration> fields,
1839 List<JS.Statement> body) { 1833 List<JS.Statement> body) {
1840 if (_extensionTypes.hasNativeSubtype(classElem.type)) { 1834 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
1841 var dartxNames = <JS.Expression>[]; 1835 var dartxNames = <JS.Expression>[];
1842 for (var m in methods) { 1836 for (var m in methods) {
1843 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 1837 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
1844 dartxNames.add(_elementMemberName(m.element, useExtension: false)); 1838 dartxNames.add(_declareMemberName(m.element, useExtension: false));
1845 } 1839 }
1846 } 1840 }
1847 for (var fieldDecl in fields) { 1841 for (var fieldDecl in fields) {
1848 if (!fieldDecl.isStatic) { 1842 if (!fieldDecl.isStatic) {
1849 for (var field in fieldDecl.fields.variables) { 1843 for (var field in fieldDecl.fields.variables) {
1850 var e = field.element as FieldElement; 1844 var e = field.element as FieldElement;
1851 if (e.isPublic) { 1845 if (e.isPublic) {
1852 dartxNames.add(_elementMemberName(e.getter, useExtension: false)); 1846 dartxNames.add(_declareMemberName(e.getter, useExtension: false));
1853 } 1847 }
1854 } 1848 }
1855 } 1849 }
1856 } 1850 }
1857 if (dartxNames.isNotEmpty) { 1851 if (dartxNames.isNotEmpty) {
1858 body.add(js.statement('dart.defineExtensionNames(#)', 1852 body.add(js.statement('dart.defineExtensionNames(#)',
1859 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 1853 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
1860 } 1854 }
1861 } 1855 }
1862 } 1856 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
2146 if (fieldNode.initializer != null) { 2140 if (fieldNode.initializer != null) {
2147 value = _visit(fieldNode.initializer); 2141 value = _visit(fieldNode.initializer);
2148 } else { 2142 } else {
2149 value = new JS.LiteralNull(); 2143 value = new JS.LiteralNull();
2150 } 2144 }
2151 fields[element] = value; 2145 fields[element] = value;
2152 }); 2146 });
2153 2147
2154 var body = <JS.Statement>[]; 2148 var body = <JS.Statement>[];
2155 fields.forEach((FieldElement e, JS.Expression initialValue) { 2149 fields.forEach((FieldElement e, JS.Expression initialValue) {
2156 if (virtualFields.containsKey(e)) { 2150 JS.Expression access = virtualFields[e] ?? _declareMemberName(e.getter);
2157 body.add( 2151 body.add(js.statement('this.# = #;', [access, initialValue]));
2158 js.statement('this[#] = #;', [virtualFields[e], initialValue]));
2159 } else {
2160 var access = _emitMemberName(e.name, type: e.enclosingElement.type);
2161 body.add(js.statement('this.# = #;', [access, initialValue]));
2162 }
2163 }); 2152 });
2164 2153
2165 if (isConst) _loader.finishTopLevel(cls.element); 2154 if (isConst) _loader.finishTopLevel(cls.element);
2166 return _statement(body); 2155 return _statement(body);
2167 } 2156 }
2168 2157
2169 FormalParameterList _parametersOf(node) { 2158 FormalParameterList _parametersOf(node) {
2170 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we 2159 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we
2171 // could handle argument initializers more consistently in a separate 2160 // could handle argument initializers more consistently in a separate
2172 // lowering pass. 2161 // lowering pass.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2290 fn.params.isNotEmpty) { 2279 fn.params.isNotEmpty) {
2291 // []= methods need to return the value. We could also address this at 2280 // []= methods need to return the value. We could also address this at
2292 // call sites, but it's cleaner to instead transform the operator method . 2281 // call sites, but it's cleaner to instead transform the operator method .
2293 fn = _alwaysReturnLastParameter(fn); 2282 fn = _alwaysReturnLastParameter(fn);
2294 } 2283 }
2295 2284
2296 fn = _makeGenericFunction(fn); 2285 fn = _makeGenericFunction(fn);
2297 } 2286 }
2298 2287
2299 return annotate( 2288 return annotate(
2300 new JS.Method( 2289 new JS.Method(_declareMemberName(node.element), fn,
2301 _elementMemberName(node.element,
2302 useExtension: _extensionTypes.isNativeClass(type.element)),
2303 fn,
2304 isGetter: node.isGetter, 2290 isGetter: node.isGetter,
2305 isSetter: node.isSetter, 2291 isSetter: node.isSetter,
2306 isStatic: node.isStatic), 2292 isStatic: node.isStatic),
2307 node, 2293 node,
2308 node.element); 2294 node.element);
2309 } 2295 }
2310 2296
2311 /// Transform the function so the last parameter is always returned. 2297 /// Transform the function so the last parameter is always returned.
2312 /// 2298 ///
2313 /// This is useful for indexed set methods, which otherwise would not have 2299 /// This is useful for indexed set methods, which otherwise would not have
(...skipping 2896 matching lines...) Expand 10 before | Expand all | Expand 10 after
5210 } 5196 }
5211 JS.Expression result = _visit(node); 5197 JS.Expression result = _visit(node);
5212 if (isNullable(node)) result = js.call('dart.test(#)', result); 5198 if (isNullable(node)) result = js.call('dart.test(#)', result);
5213 return result; 5199 return result;
5214 } 5200 }
5215 5201
5216 /// Like [_emitMemberName], but for declaration sites. 5202 /// Like [_emitMemberName], but for declaration sites.
5217 /// 5203 ///
5218 /// Unlike call sites, we always have an element available, so we can use it 5204 /// Unlike call sites, we always have an element available, so we can use it
5219 /// directly rather than computing the relevant options for [_emitMemberName]. 5205 /// directly rather than computing the relevant options for [_emitMemberName].
5220 JS.Expression _elementMemberName(ExecutableElement e, {bool useExtension}) { 5206 JS.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) {
5221 String name; 5207 String name;
5222 if (e is PropertyAccessorElement) { 5208 if (e is PropertyAccessorElement) {
5223 name = e.variable.name; 5209 name = e.variable.name;
5224 } else { 5210 } else {
5225 name = e.name; 5211 name = e.name;
5226 } 5212 }
5227 return _emitMemberName(name, 5213 return _emitMemberName(name,
5228 type: (e.enclosingElement as ClassElement).type,
5229 unary: e.parameters.isEmpty, 5214 unary: e.parameters.isEmpty,
5230 isStatic: e.isStatic, 5215 isStatic: e.isStatic,
5231 useExtension: useExtension); 5216 useExtension:
5217 useExtension ?? _extensionTypes.isNativeClass(e.enclosingElement));
5232 } 5218 }
5233 5219
5234 /// This handles member renaming for private names and operators. 5220 /// This handles member renaming for private names and operators.
5235 /// 5221 ///
5236 /// Private names are generated using ES6 symbols: 5222 /// Private names are generated using ES6 symbols:
5237 /// 5223 ///
5238 /// // At the top of the module: 5224 /// // At the top of the module:
5239 /// let _x = Symbol('_x'); 5225 /// let _x = Symbol('_x');
5240 /// let _y = Symbol('_y'); 5226 /// let _y = Symbol('_y');
5241 /// ... 5227 /// ...
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
5519 } 5505 }
5520 5506
5521 bool isLibraryPrefix(Expression node) => 5507 bool isLibraryPrefix(Expression node) =>
5522 node is SimpleIdentifier && node.staticElement is PrefixElement; 5508 node is SimpleIdentifier && node.staticElement is PrefixElement;
5523 5509
5524 LibraryElement _getLibrary(AnalysisContext c, String uri) => 5510 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
5525 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 5511 c.computeLibraryElement(c.sourceFactory.forUri(uri));
5526 5512
5527 bool _isDartRuntime(LibraryElement l) => 5513 bool _isDartRuntime(LibraryElement l) =>
5528 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 5514 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698