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

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

Issue 2847893002: fix #27258, don't allow dynamic set of a final field (Closed)
Patch Set: format Created 3 years, 7 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 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 1296
1297 // Create enum class 1297 // Create enum class
1298 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), 1298 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
1299 _emitClassHeritage(element), [constructor, toStringF]); 1299 _emitClassHeritage(element), [constructor, toStringF]);
1300 var id = _emitTopLevelName(element); 1300 var id = _emitTopLevelName(element);
1301 1301
1302 // Emit metadata for synthetic enum index member. 1302 // Emit metadata for synthetic enum index member.
1303 // TODO(jacobr): make field readonly when that is supported. 1303 // TODO(jacobr): make field readonly when that is supported.
1304 var tInstanceFields = <JS.Property>[ 1304 var tInstanceFields = <JS.Property>[
1305 new JS.Property( 1305 new JS.Property(
1306 _emitMemberName('index'), _emitAnnotatedType(intClass.type, null)) 1306 _emitMemberName('index'), _emitFieldSignature(types.intType))
1307 ]; 1307 ];
1308 var sigFields = <JS.Property>[ 1308 var sigFields = <JS.Property>[];
1309 _buildSignatureField('fields', tInstanceFields) 1309 _buildSignatureField(sigFields, 'fields', tInstanceFields);
1310 ];
1311 var sig = new JS.ObjectInitializer(sigFields); 1310 var sig = new JS.ObjectInitializer(sigFields);
1312 1311
1313 var result = [ 1312 var result = [
1314 js.statement('# = #', [id, classExpr]), 1313 js.statement('# = #', [id, classExpr]),
1315 _callHelperStatement('setSignature(#, #);', [id, sig]) 1314 _callHelperStatement('setSignature(#, #);', [id, sig])
1316 ]; 1315 ];
1317 1316
1318 // defineEnumValues internally depends on dart.constList which uses 1317 // defineEnumValues internally depends on dart.constList which uses
1319 // _interceptors.JSArray. 1318 // _interceptors.JSArray.
1320 _declareBeforeUse(_jsArray); 1319 _declareBeforeUse(_jsArray);
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1839 new JS.ArrayInitializer(names, multiline: names.length > 4) 1838 new JS.ArrayInitializer(names, multiline: names.length > 4)
1840 ])); 1839 ]));
1841 } 1840 }
1842 1841
1843 // Define mixin members (if any) on the mixin class. 1842 // Define mixin members (if any) on the mixin class.
1844 var mixinClass = js.call('#.__proto__', [className]); 1843 var mixinClass = js.call('#.__proto__', [className]);
1845 emitExtensions(mixinClass, _classProperties.mixinExtensionMembers); 1844 emitExtensions(mixinClass, _classProperties.mixinExtensionMembers);
1846 emitExtensions(className, _classProperties.extensionMembers); 1845 emitExtensions(className, _classProperties.extensionMembers);
1847 } 1846 }
1848 1847
1849 JS.Property _buildSignatureField(String name, List<JS.Property> elements) { 1848 void _buildSignatureField(
1849 List<JS.Property> sigFields, String name, List<JS.Property> elements) {
1850 if (elements.isEmpty) return;
1850 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1); 1851 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1);
1851 // TODO(vsm): Remove 1852 // TODO(vsm): Remove
1852 var e = js.call('() => #', o); 1853 var e = js.call('() => #', o);
1853 return new JS.Property(_propertyName(name), e); 1854 sigFields.add(new JS.Property(_propertyName(name), e));
1854 } 1855 }
1855 1856
1856 /// Emit the signature on the class recording the runtime type information 1857 /// Emit the signature on the class recording the runtime type information
1857 void _emitClassSignature( 1858 void _emitClassSignature(
1858 List<MethodDeclaration> methods, 1859 List<MethodDeclaration> methods,
1859 List<FieldDeclaration> fields, 1860 List<FieldDeclaration> fields,
1860 ClassElement classElem, 1861 ClassElement classElem,
1861 List<ConstructorDeclaration> ctors, 1862 List<ConstructorDeclaration> ctors,
1862 JS.Expression className, 1863 JS.Expression className,
1863 List<JS.Statement> body) { 1864 List<JS.Statement> body) {
(...skipping 13 matching lines...) Expand all
1877 var tStaticSetters = <JS.Property>[]; 1878 var tStaticSetters = <JS.Property>[];
1878 var tInstanceSetters = <JS.Property>[]; 1879 var tInstanceSetters = <JS.Property>[];
1879 var sNames = <JS.Expression>[]; 1880 var sNames = <JS.Expression>[];
1880 for (MethodDeclaration node in methods) { 1881 for (MethodDeclaration node in methods) {
1881 var name = node.name.name; 1882 var name = node.name.name;
1882 var element = resolutionMap.elementDeclaredByMethodDeclaration(node); 1883 var element = resolutionMap.elementDeclaredByMethodDeclaration(node);
1883 // TODO(vsm): Clean up all the nasty duplication. 1884 // TODO(vsm): Clean up all the nasty duplication.
1884 if (node.isAbstract) { 1885 if (node.isAbstract) {
1885 continue; 1886 continue;
1886 } 1887 }
1887 if (node.isStatic && 1888 // Static getters/setters cannot be called with dynamic dispatch, nor
1888 !options.emitMetadata && 1889 // can they be torn off.
1890 // TODO(jmesserly): can we attach static method type info at the tearoff
1891 // point, and avoid saving the information otherwise? Same trick would
1892 // work for top-level functions.
1893 if (!options.emitMetadata &&
1894 node.isStatic &&
1889 (node.isGetter || node.isSetter)) { 1895 (node.isGetter || node.isSetter)) {
1890 continue; 1896 continue;
1891 } 1897 }
1892 List<JS.Property> tMember; 1898 List<JS.Property> tMember;
1899 // TODO(jmesserly): these 3 variables should be typed.
1893 Function getOverride; 1900 Function getOverride;
1894 Function lookup; 1901 Function lookup;
1895 Function elementToType; 1902 Function elementToType;
1903 // TODO(jmesserly): we could reduce work by not saving a full function
1904 // type for getters/setters. These only need 1 type to be saved.
1896 if (node.isGetter) { 1905 if (node.isGetter) {
1897 elementToType = (ExecutableElement element) => element.type; 1906 elementToType = (ExecutableElement element) => element.type;
1898 getOverride = classElem.lookUpInheritedConcreteGetter; 1907 getOverride = classElem.lookUpInheritedConcreteGetter;
1899 lookup = classElem.type.lookUpInheritedGetter; 1908 lookup = classElem.type.lookUpInheritedGetter;
1900 tMember = node.isStatic ? tStaticGetters : tInstanceGetters; 1909 tMember = node.isStatic ? tStaticGetters : tInstanceGetters;
1901 } else if (node.isSetter) { 1910 } else if (node.isSetter) {
1902 elementToType = (ExecutableElement element) => element.type; 1911 elementToType = (ExecutableElement element) => element.type;
1903 getOverride = classElem.lookUpInheritedConcreteSetter; 1912 getOverride = classElem.lookUpInheritedConcreteSetter;
1904 lookup = classElem.type.lookUpInheritedSetter; 1913 lookup = classElem.type.lookUpInheritedSetter;
1905 tMember = node.isStatic ? tStaticSetters : tInstanceSetters; 1914 tMember = node.isStatic ? tStaticSetters : tInstanceSetters;
(...skipping 22 matching lines...) Expand all
1928 var type = _emitAnnotatedFunctionType(reifiedType, node.metadata, 1937 var type = _emitAnnotatedFunctionType(reifiedType, node.metadata,
1929 parameters: node.parameters?.parameters, 1938 parameters: node.parameters?.parameters,
1930 nameType: options.hoistSignatureTypes, 1939 nameType: options.hoistSignatureTypes,
1931 hoistType: options.hoistSignatureTypes, 1940 hoistType: options.hoistSignatureTypes,
1932 definite: true); 1941 definite: true);
1933 1942
1934 if (needsSignature) { 1943 if (needsSignature) {
1935 var memberName = _declareMemberName(element); 1944 var memberName = _declareMemberName(element);
1936 var property = new JS.Property(memberName, type); 1945 var property = new JS.Property(memberName, type);
1937 tMember.add(property); 1946 tMember.add(property);
1938 // We record the names of static methods seperately so we can 1947 // We record the names of static methods separately so we can
1939 // attach metadata to them individually. 1948 // attach metadata to them individually.
1940 // TODO(leafp): Revisit this. 1949 // TODO(leafp): Revisit this.
1941 if (node.isStatic && !node.isGetter && !node.isSetter) { 1950 if (node.isStatic && !node.isGetter && !node.isSetter) {
1942 sNames.add(memberName); 1951 sNames.add(memberName);
1943 } 1952 }
1944 } 1953 }
1945 } 1954 }
1946 1955
1947 var tInstanceFields = <JS.Property>[]; 1956 var tInstanceFields = <JS.Property>[];
1948 var tStaticFields = <JS.Property>[]; 1957 var tStaticFields = <JS.Property>[];
1949 for (FieldDeclaration node in fields) { 1958 for (FieldDeclaration node in fields) {
1950 if (!node.isStatic || options.emitMetadata) { 1959 // Only instance fields need to be saved for dynamic dispatch.
1960 var isStatic = node.isStatic;
1961 if (options.emitMetadata || !isStatic) {
1951 for (VariableDeclaration field in node.fields.variables) { 1962 for (VariableDeclaration field in node.fields.variables) {
1952 var element = field.element as FieldElement; 1963 var element = field.element as FieldElement;
1964 var fieldList = isStatic ? tStaticFields : tInstanceFields;
1965
1953 var memberName = _declareMemberName(element.getter); 1966 var memberName = _declareMemberName(element.getter);
1954 var type = _emitAnnotatedType(element.type, node.metadata); 1967 var fieldSig = _emitFieldSignature(element.type,
1955 var property = new JS.Property(memberName, type); 1968 metadata: node.metadata, isFinal: element.isFinal);
1956 (node.isStatic ? tStaticFields : tInstanceFields).add(property); 1969 fieldList.add(new JS.Property(memberName, fieldSig));
1957 } 1970 }
1958 } 1971 }
1959 } 1972 }
1960 1973
1961 var tCtors = <JS.Property>[]; 1974 var tCtors = <JS.Property>[];
1962 if (options.emitMetadata) { 1975 if (options.emitMetadata) {
1963 for (ConstructorDeclaration node in ctors) { 1976 for (ConstructorDeclaration node in ctors) {
1964 var memberName = _constructorName(node.element); 1977 var memberName = _constructorName(node.element);
1965 var element = 1978 var element =
1966 resolutionMap.elementDeclaredByConstructorDeclaration(node); 1979 resolutionMap.elementDeclaredByConstructorDeclaration(node);
1967 var type = _emitAnnotatedFunctionType(element.type, node.metadata, 1980 var type = _emitAnnotatedFunctionType(element.type, node.metadata,
1968 parameters: node.parameters.parameters, 1981 parameters: node.parameters.parameters,
1969 nameType: options.hoistSignatureTypes, 1982 nameType: options.hoistSignatureTypes,
1970 hoistType: options.hoistSignatureTypes, 1983 hoistType: options.hoistSignatureTypes,
1971 definite: true); 1984 definite: true);
1972 var property = new JS.Property(memberName, type); 1985 var property = new JS.Property(memberName, type);
1973 tCtors.add(property); 1986 tCtors.add(property);
1974 } 1987 }
1975 } 1988 }
1976 var sigFields = <JS.Property>[]; 1989 var sigFields = <JS.Property>[];
1977 if (!tCtors.isEmpty) { 1990 _buildSignatureField(sigFields, 'constructors', tCtors);
1978 sigFields.add(_buildSignatureField('constructors', tCtors)); 1991 _buildSignatureField(sigFields, 'fields', tInstanceFields);
1979 } 1992 _buildSignatureField(sigFields, 'getters', tInstanceGetters);
1980 if (!tInstanceFields.isEmpty) { 1993 _buildSignatureField(sigFields, 'setters', tInstanceSetters);
1981 sigFields.add(_buildSignatureField('fields', tInstanceFields)); 1994 _buildSignatureField(sigFields, 'methods', tInstanceMethods);
1982 } 1995 _buildSignatureField(sigFields, 'sfields', tStaticFields);
1983 if (!tInstanceGetters.isEmpty) { 1996 _buildSignatureField(sigFields, 'sgetters', tStaticGetters);
1984 sigFields.add(_buildSignatureField('getters', tInstanceGetters)); 1997 _buildSignatureField(sigFields, 'ssetters', tStaticSetters);
1985 } 1998 _buildSignatureField(sigFields, 'statics', tStaticMethods);
1986 if (!tInstanceSetters.isEmpty) {
1987 sigFields.add(_buildSignatureField('setters', tInstanceSetters));
1988 }
1989 if (!tInstanceMethods.isEmpty) {
1990 sigFields.add(_buildSignatureField('methods', tInstanceMethods));
1991 }
1992 if (!tStaticFields.isEmpty) {
1993 sigFields.add(_buildSignatureField('sfields', tStaticFields));
1994 }
1995 if (!tStaticGetters.isEmpty) {
1996 sigFields.add(_buildSignatureField('sgetters', tStaticGetters));
1997 }
1998 if (!tStaticSetters.isEmpty) {
1999 sigFields.add(_buildSignatureField('ssetters', tStaticSetters));
2000 }
2001 if (!tStaticMethods.isEmpty) { 1999 if (!tStaticMethods.isEmpty) {
2002 assert(!sNames.isEmpty); 2000 assert(!sNames.isEmpty);
2003 // Emit names so that we can lazily attach metadata to statics 2001 // Emit names so that we can lazily attach metadata to statics
2004 // TODO(leafp): revisit this strategy 2002 // TODO(leafp): revisit this strategy
2005 var aNames = new JS.Property( 2003 sigFields.add(new JS.Property(
2006 _propertyName('names'), new JS.ArrayInitializer(sNames)); 2004 _propertyName('names'), new JS.ArrayInitializer(sNames)));
2007 sigFields.add(_buildSignatureField('statics', tStaticMethods));
2008 sigFields.add(aNames);
2009 } 2005 }
2010 // We set signature here, even if empty, to simplify the work of 2006 // We set signature here, even if empty, to simplify the work of
2011 // defineExtensionMembers at runtime. See _defineExtensionMembers. 2007 // defineExtensionMembers at runtime. See _defineExtensionMembers.
2012 if (!sigFields.isEmpty || 2008 if (!sigFields.isEmpty ||
2013 _classProperties.extensionMembers.isNotEmpty || 2009 _classProperties.extensionMembers.isNotEmpty ||
2014 _classProperties.mixinExtensionMembers.isNotEmpty) { 2010 _classProperties.mixinExtensionMembers.isNotEmpty) {
2015 var sig = new JS.ObjectInitializer(sigFields); 2011 var sig = new JS.ObjectInitializer(sigFields);
2016 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); 2012 body.add(_callHelperStatement('setSignature(#, #);', [className, sig]));
2017 } 2013 }
2018 // Add static property dart._runtimeType to Object. 2014 // Add static property dart._runtimeType to Object.
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
2948 return result; 2944 return result;
2949 } 2945 }
2950 2946
2951 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata, 2947 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata,
2952 {bool nameType: true, bool hoistType: true}) { 2948 {bool nameType: true, bool hoistType: true}) {
2953 metadata ??= []; 2949 metadata ??= [];
2954 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType); 2950 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType);
2955 return _emitAnnotatedResult(typeName, metadata); 2951 return _emitAnnotatedResult(typeName, metadata);
2956 } 2952 }
2957 2953
2954 JS.Expression _emitFieldSignature(DartType type,
2955 {List<Annotation> metadata, bool isFinal: true}) {
2956 var args = [_emitType(type)];
2957 if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
2958 args.add(new JS.ArrayInitializer(
2959 metadata.map(_instantiateAnnotation).toList()));
2960 }
2961 return _callHelper(isFinal ? 'finalFieldType(#)' : 'fieldType(#)', args);
2962 }
2963
2958 JS.ArrayInitializer _emitTypeNames( 2964 JS.ArrayInitializer _emitTypeNames(
2959 List<DartType> types, List<FormalParameter> parameters, 2965 List<DartType> types, List<FormalParameter> parameters,
2960 {bool nameType: true, bool hoistType: true}) { 2966 {bool nameType: true, bool hoistType: true}) {
2961 var result = <JS.Expression>[]; 2967 var result = <JS.Expression>[];
2962 for (int i = 0; i < types.length; ++i) { 2968 for (int i = 0; i < types.length; ++i) {
2963 var metadata = parameters != null 2969 var metadata = parameters != null
2964 ? _parameterMetadata(parameters[i]) 2970 ? _parameterMetadata(parameters[i])
2965 : <Annotation>[]; 2971 : <Annotation>[];
2966 result.add(_emitAnnotatedType(types[i], metadata)); 2972 result.add(_emitAnnotatedType(types[i], metadata));
2967 } 2973 }
(...skipping 3160 matching lines...) Expand 10 before | Expand all | Expand 10 after
6128 if (targetIdentifier.staticElement is! PrefixElement) return false; 6134 if (targetIdentifier.staticElement is! PrefixElement) return false;
6129 var prefix = targetIdentifier.staticElement as PrefixElement; 6135 var prefix = targetIdentifier.staticElement as PrefixElement;
6130 6136
6131 // The library the prefix is referring to must come from a deferred import. 6137 // The library the prefix is referring to must come from a deferred import.
6132 var containingLibrary = resolutionMap 6138 var containingLibrary = resolutionMap
6133 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 6139 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
6134 .library; 6140 .library;
6135 var imports = containingLibrary.getImportsWithPrefix(prefix); 6141 var imports = containingLibrary.getImportsWithPrefix(prefix);
6136 return imports.length == 1 && imports[0].isDeferred; 6142 return imports.length == 1 && imports[0].isDeferred;
6137 } 6143 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/test/codegen_expected/BenchmarkBase.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698