Chromium Code Reviews| 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 | 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 final ClassElement _jsArray; | 118 final ClassElement _jsArray; |
| 119 | 119 |
| 120 final ClassElement boolClass; | 120 final ClassElement boolClass; |
| 121 final ClassElement intClass; | 121 final ClassElement intClass; |
| 122 final ClassElement interceptorClass; | 122 final ClassElement interceptorClass; |
| 123 final ClassElement nullClass; | 123 final ClassElement nullClass; |
| 124 final ClassElement numClass; | 124 final ClassElement numClass; |
| 125 final ClassElement objectClass; | 125 final ClassElement objectClass; |
| 126 final ClassElement stringClass; | 126 final ClassElement stringClass; |
| 127 | 127 |
| 128 ConstFieldVisitor _constField; | 128 ConstFieldVisitor _constants; |
| 129 | 129 |
| 130 /// The current function body being compiled. | 130 /// The current function body being compiled. |
| 131 FunctionBody _currentFunction; | 131 FunctionBody _currentFunction; |
| 132 | 132 |
| 133 /// Helper class for emitting elements in the proper order to allow | 133 /// Helper class for emitting elements in the proper order to allow |
| 134 /// JS to load the module. | 134 /// JS to load the module. |
| 135 ElementLoader _loader; | 135 ElementLoader _loader; |
| 136 | 136 |
| 137 BuildUnit _buildUnit; | 137 BuildUnit _buildUnit; |
| 138 | 138 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 var nodes = new HashMap<Element, AstNode>.identity(); | 269 var nodes = new HashMap<Element, AstNode>.identity(); |
| 270 var sdkBootstrappingFns = new List<FunctionElement>(); | 270 var sdkBootstrappingFns = new List<FunctionElement>(); |
| 271 for (var unit in compilationUnits) { | 271 for (var unit in compilationUnits) { |
| 272 if (_isDartRuntime(unit.element.library)) { | 272 if (_isDartRuntime(unit.element.library)) { |
| 273 sdkBootstrappingFns.addAll(unit.element.functions); | 273 sdkBootstrappingFns.addAll(unit.element.functions); |
| 274 } | 274 } |
| 275 _collectElements(unit, nodes); | 275 _collectElements(unit, nodes); |
| 276 } | 276 } |
| 277 _loader = new ElementLoader(nodes); | 277 _loader = new ElementLoader(nodes); |
| 278 if (compilationUnits.isNotEmpty) { | 278 if (compilationUnits.isNotEmpty) { |
| 279 _constField = new ConstFieldVisitor(types, | 279 _constants = new ConstFieldVisitor(context, |
| 280 dummySource: compilationUnits.first.element.source); | 280 dummySource: compilationUnits.first.element.source); |
| 281 } | 281 } |
| 282 | 282 |
| 283 // Add implicit dart:core dependency so it is first. | 283 // Add implicit dart:core dependency so it is first. |
| 284 emitLibraryName(dartCoreLibrary); | 284 emitLibraryName(dartCoreLibrary); |
| 285 | 285 |
| 286 // Emit SDK bootstrapping functions first, if any. | 286 // Emit SDK bootstrapping functions first, if any. |
| 287 sdkBootstrappingFns.forEach(_emitDeclaration); | 287 sdkBootstrappingFns.forEach(_emitDeclaration); |
| 288 | 288 |
| 289 // Visit each compilation unit and emit its code. | 289 // Visit each compilation unit and emit its code. |
| (...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2113 [ConstructorDeclaration ctor]) { | 2113 [ConstructorDeclaration ctor]) { |
| 2114 bool isConst = ctor != null && ctor.constKeyword != null; | 2114 bool isConst = ctor != null && ctor.constKeyword != null; |
| 2115 if (isConst) _loader.startTopLevel(cls.element); | 2115 if (isConst) _loader.startTopLevel(cls.element); |
| 2116 | 2116 |
| 2117 // Run field initializers if they can have side-effects. | 2117 // Run field initializers if they can have side-effects. |
| 2118 var fields = new Map<FieldElement, JS.Expression>(); | 2118 var fields = new Map<FieldElement, JS.Expression>(); |
| 2119 var unsetFields = new Map<FieldElement, VariableDeclaration>(); | 2119 var unsetFields = new Map<FieldElement, VariableDeclaration>(); |
| 2120 for (var declaration in fieldDecls) { | 2120 for (var declaration in fieldDecls) { |
| 2121 for (var fieldNode in declaration.fields.variables) { | 2121 for (var fieldNode in declaration.fields.variables) { |
| 2122 var element = fieldNode.element; | 2122 var element = fieldNode.element; |
| 2123 if (_constField.isFieldInitConstant(fieldNode)) { | 2123 if (_constants.isFieldInitConstant(fieldNode)) { |
| 2124 unsetFields[element as FieldElement] = fieldNode; | 2124 unsetFields[element as FieldElement] = fieldNode; |
| 2125 } else { | 2125 } else { |
| 2126 fields[element as FieldElement] = _visitInitializer(fieldNode); | 2126 fields[element as FieldElement] = _visitInitializer(fieldNode); |
| 2127 } | 2127 } |
| 2128 } | 2128 } |
| 2129 } | 2129 } |
| 2130 | 2130 |
| 2131 // Initialize fields from `this.fieldName` parameters. | 2131 // Initialize fields from `this.fieldName` parameters. |
| 2132 if (ctor != null) { | 2132 if (ctor != null) { |
| 2133 for (var p in ctor.parameters.parameters) { | 2133 for (var p in ctor.parameters.parameters) { |
| (...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3760 JS.Statement _emitConstantStaticField(ClassElement classElem, | 3760 JS.Statement _emitConstantStaticField(ClassElement classElem, |
| 3761 VariableDeclaration field, Set<FieldElement> staticFieldOverrides) { | 3761 VariableDeclaration field, Set<FieldElement> staticFieldOverrides) { |
| 3762 PropertyInducingElement element = field.element; | 3762 PropertyInducingElement element = field.element; |
| 3763 assert(element.isStatic); | 3763 assert(element.isStatic); |
| 3764 | 3764 |
| 3765 _loader.startCheckingReferences(); | 3765 _loader.startCheckingReferences(); |
| 3766 JS.Expression jsInit = _visitInitializer(field); | 3766 JS.Expression jsInit = _visitInitializer(field); |
| 3767 bool isLoaded = _loader.finishCheckingReferences(); | 3767 bool isLoaded = _loader.finishCheckingReferences(); |
| 3768 | 3768 |
| 3769 bool eagerInit = | 3769 bool eagerInit = |
| 3770 isLoaded && (field.isConst || _constField.isFieldInitConstant(field)); | 3770 isLoaded && (field.isConst || _constants.isFieldInitConstant(field)); |
| 3771 | 3771 |
| 3772 var fieldName = field.name.name; | 3772 var fieldName = field.name.name; |
| 3773 if (eagerInit && | 3773 if (eagerInit && |
| 3774 !JS.invalidStaticFieldName(fieldName) && | 3774 !JS.invalidStaticFieldName(fieldName) && |
| 3775 !staticFieldOverrides.contains(element)) { | 3775 !staticFieldOverrides.contains(element)) { |
| 3776 return annotate( | 3776 return annotate( |
| 3777 js.statement('#.# = #;', [ | 3777 js.statement('#.# = #;', [ |
| 3778 _emitTopLevelName(classElem), | 3778 _emitTopLevelName(classElem), |
| 3779 _emitMemberName(fieldName, isStatic: true), | 3779 _emitMemberName(fieldName, isStatic: true), |
| 3780 jsInit | 3780 jsInit |
| 3781 ]), | 3781 ]), |
| 3782 field, | 3782 field, |
| 3783 field.element); | 3783 field.element); |
| 3784 } | 3784 } |
| 3785 | 3785 |
| 3786 // This means it should be treated as a lazy field. | 3786 // This means it should be treated as a lazy field. |
| 3787 // TODO(jmesserly): we're throwing away the initializer expression, | 3787 // TODO(jmesserly): we're throwing away the initializer expression, |
| 3788 // which will force us to regenerate it. | 3788 // which will force us to regenerate it. |
| 3789 return null; | 3789 return null; |
| 3790 } | 3790 } |
| 3791 | 3791 |
| 3792 /// Emits a top-level field. | 3792 /// Emits a top-level field. |
| 3793 JS.ModuleItem _emitTopLevelField(VariableDeclaration field) { | 3793 JS.ModuleItem _emitTopLevelField(VariableDeclaration field) { |
| 3794 TopLevelVariableElement element = field.element; | 3794 TopLevelVariableElement element = field.element; |
| 3795 assert(element.isStatic); | 3795 assert(element.isStatic); |
| 3796 | 3796 |
| 3797 bool eagerInit; | 3797 bool eagerInit; |
| 3798 JS.Expression jsInit; | 3798 JS.Expression jsInit; |
| 3799 if (field.isConst || _constField.isFieldInitConstant(field)) { | 3799 if (field.isConst || _constants.isFieldInitConstant(field)) { |
| 3800 // If the field is constant, try and generate it at the top level. | 3800 // If the field is constant, try and generate it at the top level. |
| 3801 _loader.startTopLevel(element); | 3801 _loader.startTopLevel(element); |
| 3802 jsInit = _visitInitializer(field); | 3802 jsInit = _visitInitializer(field); |
| 3803 _loader.finishTopLevel(element); | 3803 _loader.finishTopLevel(element); |
| 3804 eagerInit = _loader.isLoaded(element); | 3804 eagerInit = _loader.isLoaded(element); |
| 3805 } else { | 3805 } else { |
| 3806 // TODO(jmesserly): we're visiting the initializer here, and again | 3806 // TODO(jmesserly): we're visiting the initializer here, and again |
| 3807 // later on when we emit lazy fields. That seems busted. | 3807 // later on when we emit lazy fields. That seems busted. |
| 3808 jsInit = _visitInitializer(field); | 3808 jsInit = _visitInitializer(field); |
| 3809 eagerInit = false; | 3809 eagerInit = false; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3954 assert(args.single is JS.ObjectInitializer); | 3954 assert(args.single is JS.ObjectInitializer); |
| 3955 return args.single; | 3955 return args.single; |
| 3956 } | 3956 } |
| 3957 | 3957 |
| 3958 @override | 3958 @override |
| 3959 visitInstanceCreationExpression(InstanceCreationExpression node) { | 3959 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 3960 var element = node.staticElement; | 3960 var element = node.staticElement; |
| 3961 var constructor = node.constructorName; | 3961 var constructor = node.constructorName; |
| 3962 var name = constructor.name; | 3962 var name = constructor.name; |
| 3963 var type = constructor.type.type; | 3963 var type = constructor.type.type; |
| 3964 if (node.isConst && | |
| 3965 element?.name == 'fromEnvironment' && | |
| 3966 element.library.isDartCore) { | |
| 3967 var value = node.accept(_constants.constantVisitor); | |
| 3968 | |
| 3969 if (value == null || value.isNull) { | |
| 3970 return new JS.LiteralNull(); | |
| 3971 } | |
| 3972 if (value.isUnknown) { | |
| 3973 return type == types.boolType | |
| 3974 ? js.boolean(false) | |
|
vsm
2016/11/16 19:16:22
Can you add a comment explaining this case? When
Jennifer Messerly
2016/11/16 20:11:48
Sure, as best as I can. Unfortunately behavior of
| |
| 3975 : new JS.LiteralNull(); | |
| 3976 } | |
| 3977 if (value.type == types.boolType) { | |
| 3978 var boolValue = value.toBoolValue(); | |
| 3979 return boolValue != null ? js.boolean(boolValue) : new JS.LiteralNull(); | |
| 3980 } | |
| 3981 if (value.type == types.intType) { | |
| 3982 var intValue = value.toIntValue(); | |
| 3983 return intValue != null ? js.number(intValue) : new JS.LiteralNull(); | |
| 3984 } | |
| 3985 if (value.type == types.stringType) { | |
| 3986 var stringValue = value.toStringValue(); | |
| 3987 return stringValue != null | |
| 3988 ? js.escapedString(stringValue) | |
| 3989 : new JS.LiteralNull(); | |
| 3990 } | |
| 3991 throw new StateError('failed to evaluate $node'); | |
| 3992 } | |
| 3964 return _emitInstanceCreationExpression( | 3993 return _emitInstanceCreationExpression( |
| 3965 element, type, name, node.argumentList, node.isConst); | 3994 element, type, name, node.argumentList, node.isConst); |
| 3966 } | 3995 } |
| 3967 | 3996 |
| 3968 /// True if this type is built-in to JS, and we use the values unwrapped. | 3997 /// True if this type is built-in to JS, and we use the values unwrapped. |
| 3969 /// For these types we generate a calling convention via static | 3998 /// For these types we generate a calling convention via static |
| 3970 /// "extension methods". This allows types to be extended without adding | 3999 /// "extension methods". This allows types to be extended without adding |
| 3971 /// extensions directly on the prototype. | 4000 /// extensions directly on the prototype. |
| 3972 bool isPrimitiveType(DartType t) => | 4001 bool isPrimitiveType(DartType t) => |
| 3973 typeIsPrimitiveInJS(t) || t == types.stringType; | 4002 typeIsPrimitiveInJS(t) || t == types.stringType; |
| (...skipping 1622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5596 var targetIdentifier = target as SimpleIdentifier; | 5625 var targetIdentifier = target as SimpleIdentifier; |
| 5597 | 5626 |
| 5598 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5627 if (targetIdentifier.staticElement is! PrefixElement) return false; |
| 5599 var prefix = targetIdentifier.staticElement as PrefixElement; | 5628 var prefix = targetIdentifier.staticElement as PrefixElement; |
| 5600 | 5629 |
| 5601 // The library the prefix is referring to must come from a deferred import. | 5630 // The library the prefix is referring to must come from a deferred import. |
| 5602 var containingLibrary = (target.root as CompilationUnit).element.library; | 5631 var containingLibrary = (target.root as CompilationUnit).element.library; |
| 5603 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5632 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 5604 return imports.length == 1 && imports[0].isDeferred; | 5633 return imports.length == 1 && imports[0].isDeferred; |
| 5605 } | 5634 } |
| OLD | NEW |