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

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

Issue 1235503010: fixes #219, able to compile multiple entry points (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 5 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 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;
11 import 'package:analyzer/src/generated/constant.dart'; 11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
14 import 'package:analyzer/src/generated/scanner.dart' 14 import 'package:analyzer/src/generated/scanner.dart'
15 show StringToken, Token, TokenType; 15 show StringToken, Token, TokenType;
16 import 'package:path/path.dart' as path;
17 16
18 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder; 17 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder;
19 import 'package:dev_compiler/src/codegen/reify_coercions.dart' 18 import 'package:dev_compiler/src/codegen/reify_coercions.dart'
20 show CoercionReifier; 19 show CoercionReifier;
21 20
22 // TODO(jmesserly): import from its own package 21 // TODO(jmesserly): import from its own package
23 import 'package:dev_compiler/src/js/js_ast.dart' as JS; 22 import 'package:dev_compiler/src/js/js_ast.dart' as JS;
24 import 'package:dev_compiler/src/js/js_ast.dart' show js; 23 import 'package:dev_compiler/src/js/js_ast.dart' show js;
25 24
26 import 'package:dev_compiler/devc.dart' show AbstractCompiler; 25 import 'package:dev_compiler/src/compiler.dart' show AbstractCompiler;
27 import 'package:dev_compiler/src/checker/rules.dart'; 26 import 'package:dev_compiler/src/checker/rules.dart';
28 import 'package:dev_compiler/src/info.dart'; 27 import 'package:dev_compiler/src/info.dart';
29 import 'package:dev_compiler/src/options.dart' show CodegenOptions; 28 import 'package:dev_compiler/src/options.dart' show CodegenOptions;
30 import 'package:dev_compiler/src/utils.dart'; 29 import 'package:dev_compiler/src/utils.dart';
31 30
32 import 'code_generator.dart'; 31 import 'code_generator.dart';
33 import 'js_field_storage.dart'; 32 import 'js_field_storage.dart';
34 import 'js_names.dart' as JS; 33 import 'js_names.dart' as JS;
35 import 'js_metalet.dart' as JS; 34 import 'js_metalet.dart' as JS;
36 import 'js_module_item_order.dart'; 35 import 'js_module_item_order.dart';
37 import 'js_printer.dart' show writeJsLibrary; 36 import 'js_printer.dart' show writeJsLibrary;
38 import 'side_effect_analysis.dart'; 37 import 'side_effect_analysis.dart';
39 38
40 // Various dynamic helpers we call. 39 // Various dynamic helpers we call.
41 // If renaming these, make sure to check other places like the 40 // If renaming these, make sure to check other places like the
42 // dart_runtime.js file and comments. 41 // dart_runtime.js file and comments.
43 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can 42 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can
44 // import and generate calls to, rather than dart_runtime.js 43 // import and generate calls to, rather than dart_runtime.js
45 const DPUT = 'dput'; 44 const DPUT = 'dput';
46 const DLOAD = 'dload'; 45 const DLOAD = 'dload';
47 const DINDEX = 'dindex'; 46 const DINDEX = 'dindex';
48 const DSETINDEX = 'dsetindex'; 47 const DSETINDEX = 'dsetindex';
49 const DCALL = 'dcall'; 48 const DCALL = 'dcall';
50 const DSEND = 'dsend'; 49 const DSEND = 'dsend';
51 50
52 class JSCodegenVisitor extends GeneralizingAstVisitor { 51 class JSCodegenVisitor extends GeneralizingAstVisitor {
53 final AbstractCompiler compiler; 52 final AbstractCompiler compiler;
54 final CodegenOptions options; 53 final CodegenOptions options;
55 final TypeRules rules; 54 final TypeRules rules;
56 final LibraryInfo libraryInfo; 55 final LibraryElement currentLibrary;
57
58 /// Entry point uri
59 final Uri root;
60 56
61 /// The global extension type table. 57 /// The global extension type table.
62 final HashSet<ClassElement> _extensionTypes; 58 final HashSet<ClassElement> _extensionTypes;
63 59
64 /// Information that is precomputed for this library, indicates which fields 60 /// Information that is precomputed for this library, indicates which fields
65 /// need storage slots. 61 /// need storage slots.
66 final HashSet<FieldElement> _fieldsNeedingStorage; 62 final HashSet<FieldElement> _fieldsNeedingStorage;
67 63
68 /// The variable for the target of the current `..` cascade expression. 64 /// The variable for the target of the current `..` cascade expression.
69 SimpleIdentifier _cascadeTarget; 65 SimpleIdentifier _cascadeTarget;
(...skipping 21 matching lines...) Expand all
91 87
92 ConstFieldVisitor _constField; 88 ConstFieldVisitor _constField;
93 89
94 ModuleItemLoadOrder _loader; 90 ModuleItemLoadOrder _loader;
95 91
96 /// _interceptors.JSArray<E>, used for List literals. 92 /// _interceptors.JSArray<E>, used for List literals.
97 ClassElement _jsArray; 93 ClassElement _jsArray;
98 94
99 Map<String, DartType> _objectMembers; 95 Map<String, DartType> _objectMembers;
100 96
101 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, 97 JSCodegenVisitor(AbstractCompiler compiler, this.currentLibrary,
102 this._extensionTypes, this._fieldsNeedingStorage) 98 this._extensionTypes, this._fieldsNeedingStorage)
103 : compiler = compiler, 99 : compiler = compiler,
104 options = compiler.options.codegenOptions, 100 options = compiler.options.codegenOptions,
105 rules = compiler.rules, 101 rules = compiler.rules {
106 root = compiler.entryPointUri {
107 _loader = new ModuleItemLoadOrder(_emitModuleItem); 102 _loader = new ModuleItemLoadOrder(_emitModuleItem);
108 103
109 var context = compiler.context; 104 var context = compiler.context;
110 var src = context.sourceFactory.forUri('dart:_interceptors'); 105 var src = context.sourceFactory.forUri('dart:_interceptors');
111 var interceptors = context.computeLibraryElement(src); 106 var interceptors = context.computeLibraryElement(src);
112 _jsArray = interceptors.getType('JSArray'); 107 _jsArray = interceptors.getType('JSArray');
113 108
114 _objectMembers = getObjectMemberMap(types); 109 _objectMembers = getObjectMemberMap(types);
115 } 110 }
116 111
117 LibraryElement get currentLibrary => libraryInfo.library;
118 TypeProvider get types => rules.provider; 112 TypeProvider get types => rules.provider;
119 113
120 JS.Program emitLibrary(LibraryUnit library) { 114 JS.Program emitLibrary(LibraryUnit library) {
121 String jsDefaultValue = null; 115 String jsDefaultValue = null;
122 116
123 // Modify the AST to make coercions explicit. 117 // Modify the AST to make coercions explicit.
124 new CoercionReifier(library, compiler).reify(); 118 new CoercionReifier(library, compiler).reify();
125 119
126 var unit = library.library; 120 var unit = library.library;
127 if (unit.directives.isNotEmpty) { 121 if (unit.directives.isNotEmpty) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 _qualifiedIds.forEach(unqualifyIfNeeded); 165 _qualifiedIds.forEach(unqualifyIfNeeded);
172 _qualifiedGenericIds.forEach(unqualifyIfNeeded); 166 _qualifiedGenericIds.forEach(unqualifyIfNeeded);
173 167
174 if (_exports.isNotEmpty) _moduleItems.add(js.comment('Exports:')); 168 if (_exports.isNotEmpty) _moduleItems.add(js.comment('Exports:'));
175 169
176 // TODO(jmesserly): make these immutable in JS? 170 // TODO(jmesserly): make these immutable in JS?
177 for (var name in _exports) { 171 for (var name in _exports) {
178 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); 172 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name]));
179 } 173 }
180 174
181 var jsPath = js.string(jsOutputBase(currentLibrary, root), "'"); 175 var jsPath = compiler.getModuleName(currentLibrary.source.uri);
182 176
183 // TODO(jmesserly): it would be great to run the renamer on the body, 177 // TODO(jmesserly): it would be great to run the renamer on the body,
184 // then figure out if we really need each of these parameters. 178 // then figure out if we really need each of these parameters.
185 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 179 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
186 var params = [_exportsVar, _runtimeLibVar]; 180 var params = [_exportsVar, _runtimeLibVar];
187 var processImport = (LibraryElement library, JS.TemporaryId temp, 181 var processImport = (LibraryElement library, JS.TemporaryId temp,
188 List list) { 182 List list) {
189 params.add(temp); 183 params.add(temp);
190 list.add(js.string(jsOutputBase(library, root), "'")); 184 list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
191 }; 185 };
192 186
193 var imports = [js.string('dart_runtime/dart')]; 187 var imports = [js.string('dart_runtime/dart')];
194 _imports.forEach((library, temp) { 188 _imports.forEach((library, temp) {
195 if (_loader.libraryIsLoaded(library)) { 189 if (_loader.libraryIsLoaded(library)) {
196 processImport(library, temp, imports); 190 processImport(library, temp, imports);
197 } 191 }
198 }); 192 });
199 193
200 var lazyImports = []; 194 var lazyImports = [];
201 _imports.forEach((library, temp) { 195 _imports.forEach((library, temp) {
202 if (!_loader.libraryIsLoaded(library)) { 196 if (!_loader.libraryIsLoaded(library)) {
203 processImport(library, temp, lazyImports); 197 processImport(library, temp, lazyImports);
204 } 198 }
205 }); 199 });
206 200
207 var dartxImport = 201 var dartxImport =
208 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 202 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
209 203
210 var module = js.call("function(#) { 'use strict'; #; #; }", [ 204 var module = js.call("function(#) { 'use strict'; #; #; }", [
211 params, 205 params,
212 dartxImport, 206 dartxImport,
213 _moduleItems 207 _moduleItems
214 ]); 208 ]);
215 209
216 var program = [ 210 var program = [
217 js.statement("dart_library.library(#, #, #, #, #)", [ 211 js.statement("dart_library.library(#, #, #, #, #)", [
218 jsPath, 212 js.string(jsPath, "'"),
219 jsDefaultValue != null ? jsDefaultValue : new JS.LiteralNull(), 213 jsDefaultValue != null ? jsDefaultValue : new JS.LiteralNull(),
220 js.commentExpression( 214 js.commentExpression(
221 "Imports", new JS.ArrayInitializer(imports, multiline: true)), 215 "Imports", new JS.ArrayInitializer(imports, multiline: true)),
222 js.commentExpression("Lazy imports", 216 js.commentExpression("Lazy imports",
223 new JS.ArrayInitializer(lazyImports, multiline: true)), 217 new JS.ArrayInitializer(lazyImports, multiline: true)),
224 module 218 module
225 ]) 219 ])
226 ]; 220 ];
227 221
228 return new JS.Program(program); 222 return new JS.Program(program);
(...skipping 2571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2800 } 2794 }
2801 2795
2802 void _addExtensionType(InterfaceType t) { 2796 void _addExtensionType(InterfaceType t) {
2803 if (t.isObject || !_extensionTypes.add(t.element)) return; 2797 if (t.isObject || !_extensionTypes.add(t.element)) return;
2804 t = fillDynamicTypeArgs(t, rules.provider); 2798 t = fillDynamicTypeArgs(t, rules.provider);
2805 t.interfaces.forEach(_addExtensionType); 2799 t.interfaces.forEach(_addExtensionType);
2806 t.mixins.forEach(_addExtensionType); 2800 t.mixins.forEach(_addExtensionType);
2807 _addExtensionType(t.superclass); 2801 _addExtensionType(t.superclass);
2808 } 2802 }
2809 2803
2810 String generateLibrary(LibraryUnit unit, LibraryInfo info) { 2804 String generateLibrary(LibraryUnit unit) {
2805 var library = unit.library.element.library;
2811 var fields = findFieldsNeedingStorage(unit); 2806 var fields = findFieldsNeedingStorage(unit);
2812 var codegen = new JSCodegenVisitor(compiler, info, _extensionTypes, fields); 2807 var codegen =
2808 new JSCodegenVisitor(compiler, library, _extensionTypes, fields);
2813 var module = codegen.emitLibrary(unit); 2809 var module = codegen.emitLibrary(unit);
2814 var dir = path.join(outDir, jsOutputPath(info.library, root)); 2810 var out = compiler.getOutputPath(library.source.uri);
2815 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); 2811 return writeJsLibrary(module, out, emitSourceMaps: options.emitSourceMaps);
2816 } 2812 }
2817 } 2813 }
2818 2814
2819 /// Choose a canonical name from the library element. 2815 /// Choose a canonical name from the library element.
2820 /// This never uses the library's name (the identifier in the `library` 2816 /// This never uses the library's name (the identifier in the `library`
2821 /// declaration) as it doesn't have any meaningful rules enforced. 2817 /// declaration) as it doesn't have any meaningful rules enforced.
2822 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); 2818 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library);
2823 2819
2824 /// Shorthand for identifier-like property names. 2820 /// Shorthand for identifier-like property names.
2825 /// For now, we emit them as strings and the printer restores them to 2821 /// For now, we emit them as strings and the printer restores them to
2826 /// identifiers if it can. 2822 /// identifiers if it can.
2827 // TODO(jmesserly): avoid the round tripping through quoted form. 2823 // TODO(jmesserly): avoid the round tripping through quoted form.
2828 JS.LiteralString _propertyName(String name) => js.string(name, "'"); 2824 JS.LiteralString _propertyName(String name) => js.string(name, "'");
2829 2825
2830 /// Path to file that will be generated for [info]. In case it's url is a
2831 /// `file:` url, we use [root] to determine the relative path from the entry
2832 /// point file.
2833 String jsOutputPath(LibraryElement library, Uri root) {
2834 return '${jsOutputBase(library, root)}.js';
2835 }
2836
2837 String jsOutputBase(LibraryElement library, Uri root) {
2838 var uri = library.source.uri;
2839 var filepath = path.withoutExtension(uri.path);
2840 if (uri.scheme == 'dart') {
2841 filepath = 'dart/$filepath';
2842 } else if (uri.scheme == 'file') {
2843 filepath = path.relative(filepath, from: path.dirname(root.path));
2844 } else {
2845 assert(uri.scheme == 'package');
2846 // filepath is good here, we want the output to start with a directory
2847 // matching the package name.
2848 }
2849 return filepath;
2850 }
2851
2852 // TODO(jmesserly): validate the library. See issue #135. 2826 // TODO(jmesserly): validate the library. See issue #135.
2853 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2827 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2854 2828
2855 bool _isJsPeerInterface(DartObjectImpl value) => 2829 bool _isJsPeerInterface(DartObjectImpl value) =>
2856 value.type.name == 'JsPeerInterface'; 2830 value.type.name == 'JsPeerInterface';
2857 2831
2858 // TODO(jacobr): we would like to do something like the following 2832 // TODO(jacobr): we would like to do something like the following
2859 // but we don't have summary support yet. 2833 // but we don't have summary support yet.
2860 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2834 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2861 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2835 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
(...skipping 10 matching lines...) Expand all
2872 2846
2873 class _JsThisFinder extends JS.BaseVisitor { 2847 class _JsThisFinder extends JS.BaseVisitor {
2874 bool found = false; 2848 bool found = false;
2875 visitThis(JS.This node) { 2849 visitThis(JS.This node) {
2876 found = true; 2850 found = true;
2877 } 2851 }
2878 visitNode(JS.Node node) { 2852 visitNode(JS.Node node) {
2879 if (!found) super.visitNode(node); 2853 if (!found) super.visitNode(node);
2880 } 2854 }
2881 } 2855 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698