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

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

Issue 2781443003: Fix #28120, strong mode allows field overrides (Closed)
Patch Set: fix Created 3 years, 8 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 21 matching lines...) Expand all
32 show PackageBundleAssembler; 32 show PackageBundleAssembler;
33 import 'package:analyzer/src/summary/summary_sdk.dart'; 33 import 'package:analyzer/src/summary/summary_sdk.dart';
34 import 'package:analyzer/src/task/strong/ast_properties.dart' 34 import 'package:analyzer/src/task/strong/ast_properties.dart'
35 show isDynamicInvoke, setIsDynamicInvoke, getImplicitAssignmentCast; 35 show isDynamicInvoke, setIsDynamicInvoke, getImplicitAssignmentCast;
36 import 'package:path/path.dart' show separator; 36 import 'package:path/path.dart' show separator;
37 37
38 import '../closure/closure_annotator.dart' show ClosureAnnotator; 38 import '../closure/closure_annotator.dart' show ClosureAnnotator;
39 import '../js_ast/js_ast.dart' as JS; 39 import '../js_ast/js_ast.dart' as JS;
40 import '../js_ast/js_ast.dart' show js; 40 import '../js_ast/js_ast.dart' show js;
41 import 'ast_builder.dart' show AstBuilder; 41 import 'ast_builder.dart' show AstBuilder;
42 import 'class_property_model.dart';
43 import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile; 42 import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
44 import 'element_helpers.dart'; 43 import 'element_helpers.dart';
45 import 'element_loader.dart' show ElementLoader; 44 import 'element_loader.dart' show ElementLoader;
46 import 'extension_types.dart' show ExtensionTypeSet; 45 import 'extension_types.dart' show ExtensionTypeSet;
47 import 'js_interop.dart'; 46 import 'js_interop.dart';
48 import 'js_metalet.dart' as JS; 47 import 'js_metalet.dart' as JS;
49 import 'js_names.dart' as JS; 48 import 'js_names.dart' as JS;
50 import 'js_typeref_codegen.dart' show JsTypeRefCodegen; 49 import 'js_typeref_codegen.dart' show JsTypeRefCodegen;
51 import 'module_builder.dart' show pathToJSIdentifier; 50 import 'module_builder.dart' show pathToJSIdentifier;
52 import 'nullable_type_inference.dart' show NullableTypeInference; 51 import 'nullable_type_inference.dart' show NullableTypeInference;
52 import 'property_model.dart';
53 import 'reify_coercions.dart' show CoercionReifier; 53 import 'reify_coercions.dart' show CoercionReifier;
54 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; 54 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless;
55 import 'type_utilities.dart'; 55 import 'type_utilities.dart';
56 56
57 class CodeGenerator extends GeneralizingAstVisitor 57 class CodeGenerator extends GeneralizingAstVisitor
58 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference { 58 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference {
59 final AnalysisContext context; 59 final AnalysisContext context;
60 final SummaryDataStore summaryData; 60 final SummaryDataStore summaryData;
61 61
62 final CompilerOptions options; 62 final CompilerOptions options;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 149
150 List<TypeParameterType> _typeParamInConst = null; 150 List<TypeParameterType> _typeParamInConst = null;
151 151
152 /// Whether we are currently generating code for the body of a `JS()` call. 152 /// Whether we are currently generating code for the body of a `JS()` call.
153 bool _isInForeignJS = false; 153 bool _isInForeignJS = false;
154 154
155 /// Information about virtual and overridden fields/getters/setters in the 155 /// Information about virtual and overridden fields/getters/setters in the
156 /// class we're currently compiling, or `null` if we aren't compiling a class. 156 /// class we're currently compiling, or `null` if we aren't compiling a class.
157 ClassPropertyModel _classProperties; 157 ClassPropertyModel _classProperties;
158 158
159 /// Information about virtual fields for all libraries in the current build
160 /// unit.
161 final virtualFields = new VirtualFieldModel();
162
159 CodeGenerator( 163 CodeGenerator(
160 AnalysisContext c, this.summaryData, this.options, this._extensionTypes) 164 AnalysisContext c, this.summaryData, this.options, this._extensionTypes)
161 : context = c, 165 : context = c,
162 rules = new StrongTypeSystemImpl(c.typeProvider), 166 rules = new StrongTypeSystemImpl(c.typeProvider),
163 types = c.typeProvider, 167 types = c.typeProvider,
164 _asyncStreamIterator = 168 _asyncStreamIterator =
165 _getLibrary(c, 'dart:async').getType('StreamIterator').type, 169 _getLibrary(c, 'dart:async').getType('StreamIterator').type,
166 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), 170 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'),
167 interceptorClass = 171 interceptorClass =
168 _getLibrary(c, 'dart:_interceptors').getType('Interceptor'), 172 _getLibrary(c, 'dart:_interceptors').getType('Interceptor'),
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 243 }
240 244
241 JS.Program _emitModule(List<CompilationUnit> compilationUnits, String name) { 245 JS.Program _emitModule(List<CompilationUnit> compilationUnits, String name) {
242 if (_moduleItems.isNotEmpty) { 246 if (_moduleItems.isNotEmpty) {
243 throw new StateError('Can only call emitModule once.'); 247 throw new StateError('Can only call emitModule once.');
244 } 248 }
245 249
246 // Transform the AST to make coercions explicit. 250 // Transform the AST to make coercions explicit.
247 compilationUnits = CoercionReifier.reify(compilationUnits); 251 compilationUnits = CoercionReifier.reify(compilationUnits);
248 252
249 if (compilationUnits.any((u) => _isDartRuntime( 253 if (compilationUnits.any((u) => isSdkInternalRuntime(
250 resolutionMap.elementDeclaredByCompilationUnit(u).library))) { 254 resolutionMap.elementDeclaredByCompilationUnit(u).library))) {
251 // Don't allow these to be renamed when we're building the SDK. 255 // Don't allow these to be renamed when we're building the SDK.
252 // There is JS code in dart:* that depends on their names. 256 // There is JS code in dart:* that depends on their names.
253 _runtimeModule = new JS.Identifier('dart'); 257 _runtimeModule = new JS.Identifier('dart');
254 _extensionSymbolsModule = new JS.Identifier('dartx'); 258 _extensionSymbolsModule = new JS.Identifier('dartx');
255 } else { 259 } else {
256 // Otherwise allow these to be renamed so users can write them. 260 // Otherwise allow these to be renamed so users can write them.
257 _runtimeModule = new JS.TemporaryId('dart'); 261 _runtimeModule = new JS.TemporaryId('dart');
258 _extensionSymbolsModule = new JS.TemporaryId('dartx'); 262 _extensionSymbolsModule = new JS.TemporaryId('dartx');
259 } 263 }
260 _typeTable = new TypeTable(_runtimeModule); 264 _typeTable = new TypeTable(_runtimeModule);
261 265
262 // Initialize our library variables. 266 // Initialize our library variables.
263 var items = <JS.ModuleItem>[]; 267 var items = <JS.ModuleItem>[];
264 for (var unit in compilationUnits) { 268 for (var unit in compilationUnits) {
265 var library = 269 var library =
266 resolutionMap.elementDeclaredByCompilationUnit(unit).library; 270 resolutionMap.elementDeclaredByCompilationUnit(unit).library;
267 if (unit.element != library.definingCompilationUnit) continue; 271 if (unit.element != library.definingCompilationUnit) continue;
268 272
269 var libraryTemp = _isDartRuntime(library) 273 var libraryTemp = isSdkInternalRuntime(library)
270 ? _runtimeModule 274 ? _runtimeModule
271 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); 275 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library));
272 _libraries[library] = libraryTemp; 276 _libraries[library] = libraryTemp;
273 items.add(new JS.ExportDeclaration( 277 items.add(new JS.ExportDeclaration(
274 js.call('const # = Object.create(null)', [libraryTemp]))); 278 js.call('const # = Object.create(null)', [libraryTemp])));
275 279
276 // dart:_runtime has a magic module that holds extension method symbols. 280 // dart:_runtime has a magic module that holds extension method symbols.
277 // TODO(jmesserly): find a cleaner design for this. 281 // TODO(jmesserly): find a cleaner design for this.
278 if (_isDartRuntime(library)) { 282 if (isSdkInternalRuntime(library)) {
279 items.add(new JS.ExportDeclaration(js 283 items.add(new JS.ExportDeclaration(js
280 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); 284 .call('const # = Object.create(null)', [_extensionSymbolsModule])));
281 } 285 }
282 } 286 }
283 287
284 // Collect all Element -> Node mappings, in case we need to forward declare 288 // Collect all Element -> Node mappings, in case we need to forward declare
285 // any nodes. 289 // any nodes.
286 var nodes = new HashMap<Element, AstNode>.identity(); 290 var nodes = new HashMap<Element, AstNode>.identity();
287 var sdkBootstrappingFns = new List<FunctionElement>(); 291 var sdkBootstrappingFns = new List<FunctionElement>();
288 for (var unit in compilationUnits) { 292 for (var unit in compilationUnits) {
289 if (_isDartRuntime( 293 if (isSdkInternalRuntime(
290 resolutionMap.elementDeclaredByCompilationUnit(unit).library)) { 294 resolutionMap.elementDeclaredByCompilationUnit(unit).library)) {
291 sdkBootstrappingFns.addAll( 295 sdkBootstrappingFns.addAll(
292 resolutionMap.elementDeclaredByCompilationUnit(unit).functions); 296 resolutionMap.elementDeclaredByCompilationUnit(unit).functions);
293 } 297 }
294 _collectElements(unit, nodes); 298 _collectElements(unit, nodes);
295 } 299 }
296 _loader = new ElementLoader(nodes); 300 _loader = new ElementLoader(nodes);
297 if (compilationUnits.isNotEmpty) { 301 if (compilationUnits.isNotEmpty) {
298 _constants = new ConstFieldVisitor(context, 302 _constants = new ConstFieldVisitor(context,
299 dummySource: resolutionMap 303 dummySource: resolutionMap
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 if (classElem.typeParameters.isNotEmpty) { 827 if (classElem.typeParameters.isNotEmpty) {
824 // Generic classes will be defined inside a function that closes over the 828 // Generic classes will be defined inside a function that closes over the
825 // type parameter. So we can use their local variable name directly. 829 // type parameter. So we can use their local variable name directly.
826 className = new JS.Identifier(classElem.name); 830 className = new JS.Identifier(classElem.name);
827 } else { 831 } else {
828 className = _emitTopLevelName(classElem); 832 className = _emitTopLevelName(classElem);
829 } 833 }
830 834
831 var extensions = _extensionsToImplement(classElem); 835 var extensions = _extensionsToImplement(classElem);
832 var savedClassProperties = _classProperties; 836 var savedClassProperties = _classProperties;
833 _classProperties = new ClassPropertyModel.build(classElem, extensions); 837 _classProperties =
838 new ClassPropertyModel.build(virtualFields, classElem, extensions);
834 839
835 var classExpr = _emitClassExpression( 840 var classExpr = _emitClassExpression(
836 classElem, _emitClassMethods(node, ctors, fields), 841 classElem, _emitClassMethods(node, ctors, fields),
837 fields: allFields); 842 fields: allFields);
838 843
839 var body = <JS.Statement>[]; 844 var body = <JS.Statement>[];
840 _initExtensionSymbols(classElem, methods, fields, body); 845 _initExtensionSymbols(classElem, methods, fields, body);
841 _emitSuperHelperSymbols(_superHelperSymbols, body); 846 _emitSuperHelperSymbols(_superHelperSymbols, body);
842 847
843 // Emit the class, e.g. `core.Object = class Object { ... }` 848 // Emit the class, e.g. `core.Object = class Object { ... }`
(...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after
2513 var fn = _emitFunction(node.functionExpression); 2518 var fn = _emitFunction(node.functionExpression);
2514 2519
2515 if (currentLibrary.source.isInSystemLibrary && 2520 if (currentLibrary.source.isInSystemLibrary &&
2516 _isInlineJSFunction(node.functionExpression)) { 2521 _isInlineJSFunction(node.functionExpression)) {
2517 fn = _simplifyPassThroughArrowFunCallBody(fn); 2522 fn = _simplifyPassThroughArrowFunCallBody(fn);
2518 } 2523 }
2519 2524
2520 var element = resolutionMap.elementDeclaredByFunctionDeclaration(node); 2525 var element = resolutionMap.elementDeclaredByFunctionDeclaration(node);
2521 var nameExpr = _emitTopLevelName(element); 2526 var nameExpr = _emitTopLevelName(element);
2522 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element)); 2527 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element));
2523 if (!_isDartRuntime(element.library)) { 2528 if (!isSdkInternalRuntime(element.library)) {
2524 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true) 2529 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true)
2525 .toStatement()); 2530 .toStatement());
2526 } 2531 }
2527 2532
2528 return _statement(body); 2533 return _statement(body);
2529 } 2534 }
2530 2535
2531 bool _isInlineJSFunction(FunctionExpression functionExpression) { 2536 bool _isInlineJSFunction(FunctionExpression functionExpression) {
2532 var body = functionExpression.body; 2537 var body = functionExpression.body;
2533 if (body is ExpressionFunctionBody) { 2538 if (body is ExpressionFunctionBody) {
(...skipping 1552 matching lines...) Expand 10 before | Expand all | Expand 10 after
4086 eagerInit = _loader.isLoaded(element); 4091 eagerInit = _loader.isLoaded(element);
4087 } else { 4092 } else {
4088 // TODO(jmesserly): we're visiting the initializer here, and again 4093 // TODO(jmesserly): we're visiting the initializer here, and again
4089 // later on when we emit lazy fields. That seems busted. 4094 // later on when we emit lazy fields. That seems busted.
4090 jsInit = _visitInitializer(field); 4095 jsInit = _visitInitializer(field);
4091 eagerInit = false; 4096 eagerInit = false;
4092 } 4097 }
4093 4098
4094 // Treat dart:runtime stuff as safe to eagerly evaluate. 4099 // Treat dart:runtime stuff as safe to eagerly evaluate.
4095 // TODO(jmesserly): it'd be nice to avoid this special case. 4100 // TODO(jmesserly): it'd be nice to avoid this special case.
4096 var isJSTopLevel = field.isFinal && _isDartRuntime(element.library); 4101 var isJSTopLevel = field.isFinal && isSdkInternalRuntime(element.library);
4097 if (eagerInit || isJSTopLevel) { 4102 if (eagerInit || isJSTopLevel) {
4098 // Remember that we emitted it this way, so re-export can take advantage 4103 // Remember that we emitted it this way, so re-export can take advantage
4099 // of this fact. 4104 // of this fact.
4100 _eagerTopLevelFields.add(element); 4105 _eagerTopLevelFields.add(element);
4101 4106
4102 return annotate( 4107 return annotate(
4103 js.statement('# = #;', [_emitTopLevelName(element), jsInit]), 4108 js.statement('# = #;', [_emitTopLevelName(element), jsInit]),
4104 field, 4109 field,
4105 element); 4110 element);
4106 } 4111 }
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after
5016 } 5021 }
5017 return _callHelper('#(#, #)', 5022 return _callHelper('#(#, #)',
5018 [_emitDynamicOperationName('dload'), _visit(target), name]); 5023 [_emitDynamicOperationName('dload'), _visit(target), name]);
5019 } 5024 }
5020 5025
5021 var jsTarget = _emitTarget(target, member, isStatic); 5026 var jsTarget = _emitTarget(target, member, isStatic);
5022 bool isSuper = jsTarget is JS.Super; 5027 bool isSuper = jsTarget is JS.Super;
5023 if (isSuper && 5028 if (isSuper &&
5024 !member.isSynthetic && 5029 !member.isSynthetic &&
5025 member is FieldElementImpl && 5030 member is FieldElementImpl &&
5026 !member.isVirtual) { 5031 !virtualFields.isVirtual(member)) {
5027 // If super.x is a sealed field, then x is an instance property since 5032 // If super.x is a sealed field, then x is an instance property since
5028 // subclasses cannot override x. 5033 // subclasses cannot override x.
5029 jsTarget = new JS.This(); 5034 jsTarget = new JS.This();
5030 } 5035 }
5031 5036
5032 JS.Expression result; 5037 JS.Expression result;
5033 if (member != null && member is MethodElement && !isStatic) { 5038 if (member != null && member is MethodElement && !isStatic) {
5034 // Tear-off methods: explicitly bind it. 5039 // Tear-off methods: explicitly bind it.
5035 // To be safe always use the symbolized name when binding on a native 5040 // To be safe always use the symbolized name when binding on a native
5036 // class as bind assumes the name will match the name class sigatures 5041 // class as bind assumes the name will match the name class sigatures
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
6013 6018
6014 bool operator ==(Object other) => identical(this, other); 6019 bool operator ==(Object other) => identical(this, other);
6015 } 6020 }
6016 6021
6017 bool isLibraryPrefix(Expression node) => 6022 bool isLibraryPrefix(Expression node) =>
6018 node is SimpleIdentifier && node.staticElement is PrefixElement; 6023 node is SimpleIdentifier && node.staticElement is PrefixElement;
6019 6024
6020 LibraryElement _getLibrary(AnalysisContext c, String uri) => 6025 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
6021 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 6026 c.computeLibraryElement(c.sourceFactory.forUri(uri));
6022 6027
6023 bool _isDartRuntime(LibraryElement l) =>
6024 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
6025
6026 /// Returns `true` if [target] is a prefix for a deferred library and [name] 6028 /// Returns `true` if [target] is a prefix for a deferred library and [name]
6027 /// is "loadLibrary". 6029 /// is "loadLibrary".
6028 /// 6030 ///
6029 /// If so, the expression should be compiled to call the runtime's 6031 /// If so, the expression should be compiled to call the runtime's
6030 /// "loadLibrary" helper function. 6032 /// "loadLibrary" helper function.
6031 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) { 6033 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) {
6032 if (name.name != "loadLibrary") return false; 6034 if (name.name != "loadLibrary") return false;
6033 6035
6034 if (target is! SimpleIdentifier) return false; 6036 if (target is! SimpleIdentifier) return false;
6035 var targetIdentifier = target as SimpleIdentifier; 6037 var targetIdentifier = target as SimpleIdentifier;
6036 6038
6037 if (targetIdentifier.staticElement is! PrefixElement) return false; 6039 if (targetIdentifier.staticElement is! PrefixElement) return false;
6038 var prefix = targetIdentifier.staticElement as PrefixElement; 6040 var prefix = targetIdentifier.staticElement as PrefixElement;
6039 6041
6040 // The library the prefix is referring to must come from a deferred import. 6042 // The library the prefix is referring to must come from a deferred import.
6041 var containingLibrary = resolutionMap 6043 var containingLibrary = resolutionMap
6042 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 6044 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
6043 .library; 6045 .library;
6044 var imports = containingLibrary.getImportsWithPrefix(prefix); 6046 var imports = containingLibrary.getImportsWithPrefix(prefix);
6045 return imports.length == 1 && imports[0].isDeferred; 6047 return imports.length == 1 && imports[0].isDeferred;
6046 } 6048 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/class_property_model.dart ('k') | pkg/dev_compiler/lib/src/compiler/element_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698