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

Side by Side Diff: lib/src/codegen/js_module_item_order.dart

Issue 1636233002: fixes #427, static fields emitted outside the scope of their class (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 10 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 // 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; 5 import 'dart:collection' show HashMap;
6 6
7 import 'package:analyzer/src/generated/ast.dart'; 7 import 'package:analyzer/src/generated/ast.dart';
8 import 'package:analyzer/src/generated/element.dart'; 8 import 'package:analyzer/src/generated/element.dart';
9 9
10 import '../compiler.dart' show corelibOrder; 10 import '../compiler.dart' show corelibOrder;
(...skipping 23 matching lines...) Expand all
34 34
35 /// The current element being loaded. 35 /// The current element being loaded.
36 /// We can use this to determine if we're loading top-level code or not: 36 /// We can use this to determine if we're loading top-level code or not:
37 /// 37 ///
38 /// _currentElements.last == _topLevelElements.last 38 /// _currentElements.last == _topLevelElements.last
39 final _currentElements = new List<Element>(); 39 final _currentElements = new List<Element>();
40 40
41 /// Memoized results of [_inLibraryCycle]. 41 /// Memoized results of [_inLibraryCycle].
42 final _libraryCycleMemo = new HashMap<LibraryElement, bool>(); 42 final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
43 43
44 bool _checkReferences;
45
44 final ModuleItemEmitter _emitModuleItem; 46 final ModuleItemEmitter _emitModuleItem;
45 47
46 LibraryElement _currentLibrary; 48 LibraryElement _currentLibrary;
47 49
48 ModuleItemLoadOrder(this._emitModuleItem); 50 ModuleItemLoadOrder(this._emitModuleItem);
49 51
50 bool isLoaded(Element e) => (e.library == _currentLibrary) 52 bool isLoaded(Element e) => (e.library == _currentLibrary)
51 ? _loaded[e] == true 53 ? _loaded[e] == true
52 : libraryIsLoaded(e.library); 54 : libraryIsLoaded(e.library);
53 55
56 /// True if the element is currently being loaded.
57 bool _isLoading(Element e) => _currentElements.contains(e);
58
54 /// Collect top-level elements and nodes we need to emit. 59 /// Collect top-level elements and nodes we need to emit.
55 void collectElements( 60 void collectElements(
56 LibraryElement library, Iterable<CompilationUnit> partsThenLibrary) { 61 LibraryElement library, Iterable<CompilationUnit> partsThenLibrary) {
57 assert(_currentLibrary == null); 62 assert(_currentLibrary == null);
58 _currentLibrary = library; 63 _currentLibrary = library;
59 64
60 for (var unit in partsThenLibrary) { 65 for (var unit in partsThenLibrary) {
61 for (var decl in unit.declarations) { 66 for (var decl in unit.declarations) {
62 _declarationNodes[decl.element] = decl; 67 _declarationNodes[decl.element] = decl;
63 68
64 if (decl is ClassDeclaration) { 69 if (decl is TopLevelVariableDeclaration) {
65 for (var member in decl.members) {
66 if (member is FieldDeclaration && member.isStatic) {
67 _collectElementsForVariable(member.fields);
68 }
69 }
70 } else if (decl is TopLevelVariableDeclaration) {
71 _collectElementsForVariable(decl.variables); 70 _collectElementsForVariable(decl.variables);
72 } 71 }
73 } 72 }
74 } 73 }
75 } 74 }
76 75
77 void _collectElementsForVariable(VariableDeclarationList fields) { 76 void _collectElementsForVariable(VariableDeclarationList fields) {
78 for (var field in fields.variables) { 77 for (var field in fields.variables) {
79 _declarationNodes[field.element] = field; 78 _declarationNodes[field.element] = field;
80 } 79 }
81 } 80 }
82 81
83 /// Start generating top-level code for the element [e]. 82 /// Start generating top-level code for the element [e].
84 /// Subsequent [loadElement] calls will cause those elements to be generated 83 /// Subsequent [loadElement] calls will cause those elements to be generated
85 /// before this one, until [finishElement] is called. 84 /// before this one, until [finishElement] is called.
86 void startTopLevel(Element e) { 85 void startTopLevel(Element e) {
87 assert(isCurrentElement(e)); 86 assert(isCurrentElement(e));
88 // Assume loading will succeed until proven otherwise.
89 _loaded[e] = true;
90 _topLevelElements.add(e); 87 _topLevelElements.add(e);
91 } 88 }
92 89
93 /// Finishes the top-level code for the element [e]. 90 /// Finishes the top-level code for the element [e].
94 void finishTopLevel(Element e) { 91 void finishTopLevel(Element e) {
95 var last = _topLevelElements.removeLast(); 92 var last = _topLevelElements.removeLast();
96 assert(identical(e, last)); 93 assert(identical(e, last));
97 } 94 }
98 95
96 /// Starts recording calls to [declareBeforeUse], until
97 /// [finishCheckingReferences] is called.
98 void startCheckingReferences() {
99 // This function should not be reentrant, and we should not current be
100 // emitting top-level code.
101 assert(_checkReferences == null);
102 assert(
103 _topLevelElements.isEmpty || !isCurrentElement(_topLevelElements.last));
104 // Assume true until proven otherwise
105 _checkReferences = true;
106 }
107
108 /// Finishes recording references, and returns `true` if all referenced
109 /// items were loaded (or if no items were referenced).
110 bool finishCheckingReferences() {
111 var result = _checkReferences;
112 _checkReferences = null;
113 return result;
114 }
115
99 // Starts generating code for the declaration element [e]. 116 // Starts generating code for the declaration element [e].
100 // 117 //
101 // Normally this is called implicitly by [loadDeclaration] and/or 118 // Normally this is called implicitly by [loadDeclaration] and/or
102 // [loadElement]. However, for synthetic elements (like temporary variables) 119 // [loadElement]. However, for synthetic elements (like temporary variables)
103 // it must be called explicitly, and paired with a call to [finishElement]. 120 // it must be called explicitly, and paired with a call to [finishElement].
104 void startDeclaration(Element e) { 121 void startDeclaration(Element e) {
105 // Assume load will succeed until proven otherwise. 122 // Assume load will succeed until proven otherwise.
106 _loaded[e] = true; 123 _loaded[e] = true;
107 _currentElements.add(e); 124 _currentElements.add(e);
108 } 125 }
(...skipping 30 matching lines...) Expand all
139 /// 156 ///
140 /// This function takes care of that, and also detects cases where reordering 157 /// This function takes care of that, and also detects cases where reordering
141 /// failed, and we need to resort to lazy loading, by marking the element as 158 /// failed, and we need to resort to lazy loading, by marking the element as
142 /// lazy. All elements need to be aware of this possibility and generate code 159 /// lazy. All elements need to be aware of this possibility and generate code
143 /// accordingly. 160 /// accordingly.
144 /// 161 ///
145 /// If we are not emitting top-level code, this does nothing, because all 162 /// If we are not emitting top-level code, this does nothing, because all
146 /// declarations are assumed to be available before we start execution. 163 /// declarations are assumed to be available before we start execution.
147 /// See [startTopLevel]. 164 /// See [startTopLevel].
148 void declareBeforeUse(Element e) { 165 void declareBeforeUse(Element e) {
149 if (e == null || _topLevelElements.isEmpty) return; 166 if (e == null) return;
150 if (!isCurrentElement(_topLevelElements.last)) return; 167
168 if (_checkReferences != null) {
169 _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
170 return;
171 }
172
173 if (_topLevelElements.isEmpty ||
174 !isCurrentElement(_topLevelElements.last)) {
175 return;
176 }
151 177
152 // If the item is from our library, try to emit it now. 178 // If the item is from our library, try to emit it now.
153 bool loaded; 179 bool loaded;
154 if (e.library == _currentLibrary) { 180 if (e.library == _currentLibrary) {
155 // Type parameters are not in scope when generating hoisted fields. 181 // Type parameters are not in scope when generating hoisted fields.
156 if (e is TypeParameterElement && 182 if (e is TypeParameterElement &&
157 _currentElements.last is VariableElement) { 183 _currentElements.last is VariableElement) {
158 loaded = false; 184 loaded = false;
159 } else { 185 } else {
160 var node = _declarationNodes[e]; 186 var node = _declarationNodes[e];
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 } 256 }
231 return _libraryCycleMemo[library] = result; 257 return _libraryCycleMemo[library] = result;
232 } 258 }
233 259
234 /// Returns whether this is a library imported with 'dart:' URI. 260 /// Returns whether this is a library imported with 'dart:' URI.
235 /// 261 ///
236 /// This is similar to [LibraryElement.isInSdk], but checking the URI instead 262 /// This is similar to [LibraryElement.isInSdk], but checking the URI instead
237 /// of the library naming convention, because the URI is reliable. 263 /// of the library naming convention, because the URI is reliable.
238 static bool _isDartUri(LibraryElement e) => e.source.uri.scheme == 'dart'; 264 static bool _isDartUri(LibraryElement e) => e.source.uri.scheme == 'dart';
239 } 265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698