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 // 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 library dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
6 | 6 |
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
(...skipping 20 matching lines...) Expand all Loading... |
31 import '../utils.dart'; | 31 import '../utils.dart'; |
32 | 32 |
33 import 'code_generator.dart'; | 33 import 'code_generator.dart'; |
34 import 'js_field_storage.dart'; | 34 import 'js_field_storage.dart'; |
35 import 'js_interop.dart'; | 35 import 'js_interop.dart'; |
36 import 'js_names.dart' as JS; | 36 import 'js_names.dart' as JS; |
37 import 'js_metalet.dart' as JS; | 37 import 'js_metalet.dart' as JS; |
38 import 'js_module_item_order.dart'; | 38 import 'js_module_item_order.dart'; |
39 import 'js_names.dart'; | 39 import 'js_names.dart'; |
40 import 'js_printer.dart' show writeJsLibrary; | 40 import 'js_printer.dart' show writeJsLibrary; |
| 41 import 'module_builder.dart'; |
41 import 'side_effect_analysis.dart'; | 42 import 'side_effect_analysis.dart'; |
42 | 43 |
43 // Various dynamic helpers we call. | 44 // Various dynamic helpers we call. |
44 // If renaming these, make sure to check other places like the | 45 // If renaming these, make sure to check other places like the |
45 // _runtime.js file and comments. | 46 // _runtime.js file and comments. |
46 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can | 47 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can |
47 // import and generate calls to, rather than dart_runtime.js | 48 // import and generate calls to, rather than dart_runtime.js |
48 const DPUT = 'dput'; | 49 const DPUT = 'dput'; |
49 const DLOAD = 'dload'; | 50 const DLOAD = 'dload'; |
50 const DINDEX = 'dindex'; | 51 const DINDEX = 'dindex'; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 _flushLibraryProperties(_moduleItems); | 172 _flushLibraryProperties(_moduleItems); |
172 | 173 |
173 // Mark all qualified names as qualified or not, depending on if they need | 174 // Mark all qualified names as qualified or not, depending on if they need |
174 // to be loaded lazily or not. | 175 // to be loaded lazily or not. |
175 for (var elementIdPairs in _qualifiedIds) { | 176 for (var elementIdPairs in _qualifiedIds) { |
176 var element = elementIdPairs.e0; | 177 var element = elementIdPairs.e0; |
177 var id = elementIdPairs.e1; | 178 var id = elementIdPairs.e1; |
178 id.setQualified(!_loader.isLoaded(element)); | 179 id.setQualified(!_loader.isLoaded(element)); |
179 } | 180 } |
180 | 181 |
181 if (_exports.isNotEmpty) _moduleItems.add(js.comment('Exports:')); | 182 var moduleBuilder = new ModuleBuilder( |
| 183 compiler.getModuleName(currentLibrary.source.uri), |
| 184 _jsModuleValue, |
| 185 _exportsVar, |
| 186 options.moduleFormat); |
182 | 187 |
183 // TODO(jmesserly): make these immutable in JS? | 188 _exports.forEach(moduleBuilder.addExport); |
184 for (var name in _exports) { | |
185 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); | |
186 } | |
187 | 189 |
188 var jsPath = compiler.getModuleName(currentLibrary.source.uri); | 190 var items = <JS.ModuleItem>[]; |
189 | |
190 // TODO(jmesserly): it would be great to run the renamer on the body, | |
191 // then figure out if we really need each of these parameters. | |
192 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 | |
193 var params = [_exportsVar]; | |
194 var lazyParams = []; | |
195 | |
196 var imports = <JS.Expression>[]; | |
197 var lazyImports = <JS.Expression>[]; | |
198 var moduleStatements = <JS.Statement>[]; | |
199 | |
200 addImport(String name, JS.Expression libVar, {bool lazy: false}) { | |
201 (lazy ? lazyImports : imports).add(js.string(name, "'")); | |
202 (lazy ? lazyParams : params).add(libVar); | |
203 } | |
204 | |
205 if (!_isDartRuntime) { | 191 if (!_isDartRuntime) { |
206 addImport('dart/_runtime', _runtimeLibVar); | 192 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar); |
207 | 193 |
208 var dartxImport = | 194 var dartxImport = |
209 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); | 195 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); |
210 moduleStatements.add(dartxImport); | 196 items.add(dartxImport); |
211 } | 197 } |
| 198 items.addAll(_moduleItems); |
| 199 |
212 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { | 200 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { |
213 addImport(compiler.getModuleName(lib.source.uri), temp, | 201 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp, |
214 lazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); | 202 isLazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); |
215 }); | 203 }); |
216 params.addAll(lazyParams); | |
217 | |
218 moduleStatements.addAll(_moduleItems); | |
219 | |
220 var module = | |
221 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); | |
222 | |
223 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ | |
224 js.string(jsPath, "'"), | |
225 _jsModuleValue ?? new JS.LiteralNull(), | |
226 js.commentExpression( | |
227 "Imports", new JS.ArrayInitializer(imports, multiline: true)), | |
228 js.commentExpression("Lazy imports", | |
229 new JS.ArrayInitializer(lazyImports, multiline: true)), | |
230 module | |
231 ]); | |
232 | 204 |
233 // TODO(jmesserly): scriptTag support. | 205 // TODO(jmesserly): scriptTag support. |
234 // Enable this if we know we're targetting command line environment? | 206 // Enable this if we know we're targetting command line environment? |
235 // It doesn't work in browser. | 207 // It doesn't work in browser. |
236 // var jsBin = compiler.options.runnerOptions.v8Binary; | 208 // var jsBin = compiler.options.runnerOptions.v8Binary; |
237 // String scriptTag = null; | 209 // String scriptTag = null; |
238 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; | 210 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; |
239 return new JS.Program(<JS.Statement>[moduleDef]); | 211 return moduleBuilder.build(items); |
240 } | 212 } |
241 | 213 |
242 void _emitModuleItem(AstNode node) { | 214 void _emitModuleItem(AstNode node) { |
243 // Attempt to group adjacent fields/properties. | 215 // Attempt to group adjacent fields/properties. |
244 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems); | 216 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems); |
245 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); | 217 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); |
246 | 218 |
247 var code = _visit(node); | 219 var code = _visit(node); |
248 if (code != null) _moduleItems.add(code); | 220 if (code != null) _moduleItems.add(code); |
249 } | 221 } |
(...skipping 3370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3620 | 3592 |
3621 /// A special kind of element created by the compiler, signifying a temporary | 3593 /// A special kind of element created by the compiler, signifying a temporary |
3622 /// variable. These objects use instance equality, and should be shared | 3594 /// variable. These objects use instance equality, and should be shared |
3623 /// everywhere in the tree where they are treated as the same variable. | 3595 /// everywhere in the tree where they are treated as the same variable. |
3624 class TemporaryVariableElement extends LocalVariableElementImpl { | 3596 class TemporaryVariableElement extends LocalVariableElementImpl { |
3625 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3597 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3626 | 3598 |
3627 int get hashCode => identityHashCode(this); | 3599 int get hashCode => identityHashCode(this); |
3628 bool operator ==(Object other) => identical(this, other); | 3600 bool operator ==(Object other) => identical(this, other); |
3629 } | 3601 } |
OLD | NEW |