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

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

Issue 1013653004: Suppress generation of JsGlobal and JsType code and use window as the default value instead of {} f… (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Created 5 years, 9 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; 7 import 'dart:collection' show HashSet;
8 import 'dart:io' show Directory, File; 8 import 'dart:io' show Directory, File;
9 9
10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
(...skipping 16 matching lines...) Expand all
27 import 'package:dev_compiler/src/checker/rules.dart'; 27 import 'package:dev_compiler/src/checker/rules.dart';
28 import 'package:dev_compiler/src/info.dart'; 28 import 'package:dev_compiler/src/info.dart';
29 import 'package:dev_compiler/src/options.dart'; 29 import 'package:dev_compiler/src/options.dart';
30 import 'package:dev_compiler/src/report.dart'; 30 import 'package:dev_compiler/src/report.dart';
31 import 'package:dev_compiler/src/utils.dart'; 31 import 'package:dev_compiler/src/utils.dart';
32 import 'code_generator.dart'; 32 import 'code_generator.dart';
33 33
34 // This must match the optional parameter name used in runtime.js 34 // This must match the optional parameter name used in runtime.js
35 const String _jsNamedParameterName = r'opt$'; 35 const String _jsNamedParameterName = r'opt$';
36 36
37 bool _isAnnotationType(Annotation m, String name) => m.name.name == name;
38
39 bool _hasAnnotationType(AnnotatedNode node, String name) =>
40 node.metadata.any((annotation) => _isAnnotationType(annotation, name));
41
37 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { 42 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
38 final LibraryInfo libraryInfo; 43 final LibraryInfo libraryInfo;
39 final TypeRules rules; 44 final TypeRules rules;
40 45
41 /// The variable for the target of the current `..` cascade expression. 46 /// The variable for the target of the current `..` cascade expression.
42 SimpleIdentifier _cascadeTarget; 47 SimpleIdentifier _cascadeTarget;
43 /// The variable for the current catch clause 48 /// The variable for the current catch clause
44 String _catchParameter; 49 String _catchParameter;
45 50
46 ClassDeclaration currentClass; 51 ClassDeclaration currentClass;
47 ConstantEvaluator _constEvaluator; 52 ConstantEvaluator _constEvaluator;
53 bool _containsJsGlobals = false;
Jennifer Messerly 2015/03/17 16:39:18 should this be explicit on the library tag? e.g. l
Jacob 2015/03/17 21:22:44 Discussed offline. Switched to @JsName here and fo
48 54
49 final _exports = <String>[]; 55 final _exports = <String>[];
50 final _lazyFields = <VariableDeclaration>[]; 56 final _lazyFields = <VariableDeclaration>[];
51 final _properties = <FunctionDeclaration>[]; 57 final _properties = <FunctionDeclaration>[];
52 final _privateNames = new HashSet<String>(); 58 final _privateNames = new HashSet<String>();
53 final _pendingPrivateNames = <String>[]; 59 final _pendingPrivateNames = <String>[];
54 60
55 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) 61 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules)
56 : libraryInfo = libraryInfo, 62 : libraryInfo = libraryInfo,
57 rules = rules; 63 rules = rules;
(...skipping 15 matching lines...) Expand all
73 } 79 }
74 80
75 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); 81 if (_exports.isNotEmpty) body.add(js.comment('Exports:'));
76 82
77 // TODO(jmesserly): make these immutable in JS? 83 // TODO(jmesserly): make these immutable in JS?
78 for (var name in _exports) { 84 for (var name in _exports) {
79 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); 85 body.add(js.statement('$_EXPORTS.# = #;', [name, name]));
80 } 86 }
81 87
82 var name = jsLibraryName(libraryInfo.library); 88 var name = jsLibraryName(libraryInfo.library);
89 var defaultValue = _containsJsGlobals ? 'window' : '{}';
Jennifer Messerly 2015/03/17 16:39:18 normally we'd do this as an interpolated expressio
Jacob 2015/03/17 21:22:44 Done.
83 return new JS.Program([ 90 return new JS.Program([
84 js.statement('var #;', name), 91 js.statement('var #;', name),
85 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = {}));", 92 js.statement(
93 "(function($_EXPORTS) { 'use strict'; #; })(# || (# = $defaultValue)); ",
Jennifer Messerly 2015/03/17 16:39:18 this should be: "(function($_EXPORTS) { 'use stric
Jacob 2015/03/17 21:22:44 Done.
86 [body, name, name]) 94 [body, name, name])
Jennifer Messerly 2015/03/17 16:39:18 [body, name, name, defaultValue]
Jacob 2015/03/17 21:22:44 Done.
87 ]); 95 ]);
88 } 96 }
89 97
90 JS.Statement _initPrivateSymbol(String name) => 98 JS.Statement _initPrivateSymbol(String name) =>
91 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); 99 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]);
92 100
93 @override 101 @override
94 JS.Statement visitCompilationUnit(CompilationUnit node) { 102 JS.Statement visitCompilationUnit(CompilationUnit node) {
95 // TODO(jmesserly): scriptTag, directives. 103 // TODO(jmesserly): scriptTag, directives.
96 var body = <JS.Statement>[]; 104 var body = <JS.Statement>[];
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 var dynInst = js.statement('let # = #(#);', [name, genericName, typeArgs]); 232 var dynInst = js.statement('let # = #(#);', [name, genericName, typeArgs]);
225 233
226 // TODO(jmesserly): is it worth exporting both names? Alternatively we could 234 // TODO(jmesserly): is it worth exporting both names? Alternatively we could
227 // put the generic type constructor on the <dynamic> instance. 235 // put the generic type constructor on the <dynamic> instance.
228 if (isPublic(name)) _exports.add('${name}\$'); 236 if (isPublic(name)) _exports.add('${name}\$');
229 return new JS.Block([genericDef, dynInst]); 237 return new JS.Block([genericDef, dynInst]);
230 } 238 }
231 239
232 @override 240 @override
233 JS.Statement visitClassDeclaration(ClassDeclaration node) { 241 JS.Statement visitClassDeclaration(ClassDeclaration node) {
242 if (_hasAnnotationType(node, 'JsType')) return null;
243
234 currentClass = node; 244 currentClass = node;
235 245
236 var body = <JS.Statement>[]; 246 var body = <JS.Statement>[];
237 247
238 var name = node.name.name; 248 var name = node.name.name;
239 var ctors = <ConstructorDeclaration>[]; 249 var ctors = <ConstructorDeclaration>[];
240 var fields = <FieldDeclaration>[]; 250 var fields = <FieldDeclaration>[];
241 var staticFields = <FieldDeclaration>[]; 251 var staticFields = <FieldDeclaration>[];
242 for (var member in node.members) { 252 for (var member in node.members) {
243 if (member is ConstructorDeclaration) { 253 if (member is ConstructorDeclaration) {
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 JS.Statement visitAssertStatement(AssertStatement node) => 917 JS.Statement visitAssertStatement(AssertStatement node) =>
908 // TODO(jmesserly): only emit in checked mode. 918 // TODO(jmesserly): only emit in checked mode.
909 js.statement('dart.assert(#);', _visit(node.condition)); 919 js.statement('dart.assert(#);', _visit(node.condition));
910 920
911 @override 921 @override
912 JS.Return visitReturnStatement(ReturnStatement node) => 922 JS.Return visitReturnStatement(ReturnStatement node) =>
913 new JS.Return(_visit(node.expression)); 923 new JS.Return(_visit(node.expression));
914 924
915 @override 925 @override
916 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 926 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
927 if (_hasAnnotationType(node, 'JsGlobal')) {
928 _containsJsGlobals = true;
Jennifer Messerly 2015/03/17 16:39:18 per suggestion above, this won't be needed
929 return null;
930 }
917 var body = <JS.Statement>[]; 931 var body = <JS.Statement>[];
918 932
919 for (var field in node.variables.variables) { 933 for (var field in node.variables.variables) {
920 if (field.isConst) { 934 if (field.isConst) {
921 // constant fields don't change, so we can generate them as `let` 935 // constant fields don't change, so we can generate them as `let`
922 // but add them to the module's exports 936 // but add them to the module's exports
923 var name = field.name.name; 937 var name = field.name.name;
924 body.add(js.statement('let # = #;', [ 938 body.add(js.statement('let # = #;', [
925 new JS.VariableDeclaration(name), 939 new JS.VariableDeclaration(name),
926 _visitInitializer(field) 940 _visitInitializer(field)
(...skipping 26 matching lines...) Expand all
953 // var result = []; 967 // var result = [];
954 // result.length = length; 968 // result.length = length;
955 var savedCascadeTemp = _cascadeTarget; 969 var savedCascadeTemp = _cascadeTarget;
956 _cascadeTarget = last.name; 970 _cascadeTarget = last.name;
957 971
958 variables = _visitList(node.variables.take(node.variables.length - 1)); 972 variables = _visitList(node.variables.take(node.variables.length - 1));
959 variables.add(new JS.VariableInitialization( 973 variables.add(new JS.VariableInitialization(
960 new JS.VariableDeclaration(last.name.name), 974 new JS.VariableDeclaration(last.name.name),
961 _visit(lastInitializer.target))); 975 _visit(lastInitializer.target)));
962 976
963 var result = 977 var result = <JS.Expression>[
Siggi Cherem (dart-lang) 2015/03/17 01:25:36 DBC - you might need to run pub-ugprade, seems lik
964 <JS.Expression>[new JS.VariableDeclarationList('let', variables)]; 978 new JS.VariableDeclarationList('let', variables)
979 ];
965 result.addAll(_visitList(lastInitializer.cascadeSections)); 980 result.addAll(_visitList(lastInitializer.cascadeSections));
966 _cascadeTarget = savedCascadeTemp; 981 _cascadeTarget = savedCascadeTemp;
967 return _statement(result.map((e) => new JS.ExpressionStatement(e))); 982 return _statement(result.map((e) => new JS.ExpressionStatement(e)));
968 } else { 983 } else {
969 variables = _visitList(node.variables); 984 variables = _visitList(node.variables);
970 } 985 }
971 986
972 return new JS.VariableDeclarationList('let', variables); 987 return new JS.VariableDeclarationList('let', variables);
973 } 988 }
974 989
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 isSetter: true)); 1024 isSetter: true));
1010 } 1025 }
1011 } 1026 }
1012 1027
1013 return js.statement( 1028 return js.statement(
1014 'dart.defineLazyProperties(#, { # })', [objExpr, methods]); 1029 'dart.defineLazyProperties(#, { # })', [objExpr, methods]);
1015 } 1030 }
1016 1031
1017 void _flushLibraryProperties(List<JS.Statement> body) { 1032 void _flushLibraryProperties(List<JS.Statement> body) {
1018 if (_properties.isEmpty) return; 1033 if (_properties.isEmpty) return;
1019 body.add(js.statement('dart.copyProperties($_EXPORTS, { # });', 1034 body.add(js.statement('dart.copyProperties($_EXPORTS, { # });', [
1020 [_properties.map(_emitTopLevelProperty)])); 1035 _properties.map(_emitTopLevelProperty)
1036 ]));
1021 _properties.clear(); 1037 _properties.clear();
1022 } 1038 }
1023 1039
1024 @override 1040 @override
1025 JS.Statement visitVariableDeclarationStatement( 1041 JS.Statement visitVariableDeclarationStatement(
1026 VariableDeclarationStatement node) => 1042 VariableDeclarationStatement node) =>
1027 _expressionStatement(_visit(node.variables)); 1043 _expressionStatement(_visit(node.variables));
1028 1044
1029 @override 1045 @override
1030 visitConstructorName(ConstructorName node) { 1046 visitConstructorName(ConstructorName node) {
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 1618
1603 @override 1619 @override
1604 visitDoubleLiteral(DoubleLiteral node) => js.number(node.value); 1620 visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
1605 1621
1606 @override 1622 @override
1607 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); 1623 visitNullLiteral(NullLiteral node) => new JS.LiteralNull();
1608 1624
1609 @override 1625 @override
1610 visitListLiteral(ListLiteral node) { 1626 visitListLiteral(ListLiteral node) {
1611 // TODO(jmesserly): make this faster. We're wasting an array. 1627 // TODO(jmesserly): make this faster. We're wasting an array.
1612 var list = js.call('new List.from(#)', 1628 var list = js.call('new List.from(#)', [
1613 [new JS.ArrayInitializer(_visitList(node.elements))]); 1629 new JS.ArrayInitializer(_visitList(node.elements))
1630 ]);
1614 if (node.constKeyword != null) { 1631 if (node.constKeyword != null) {
1615 list = js.commentExpression('Unimplemented const', list); 1632 list = js.commentExpression('Unimplemented const', list);
1616 } 1633 }
1617 return list; 1634 return list;
1618 } 1635 }
1619 1636
1620 @override 1637 @override
1621 visitMapLiteral(MapLiteral node) { 1638 visitMapLiteral(MapLiteral node) {
1622 var entries = node.entries; 1639 var entries = node.entries;
1623 var mapArguments = null; 1640 var mapArguments = null;
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 CheckerReporter reporter) { 1946 CheckerReporter reporter) {
1930 JS.Program jsTree = 1947 JS.Program jsTree =
1931 new JSCodegenVisitor(info, rules).generateLibrary(units, reporter); 1948 new JSCodegenVisitor(info, rules).generateLibrary(units, reporter);
1932 1949
1933 var outputPath = path.join(outDir, jsOutputPath(info, root)); 1950 var outputPath = path.join(outDir, jsOutputPath(info, root));
1934 new Directory(path.dirname(outputPath)).createSync(recursive: true); 1951 new Directory(path.dirname(outputPath)).createSync(recursive: true);
1935 1952
1936 if (options.emitSourceMaps) { 1953 if (options.emitSourceMaps) {
1937 var outFilename = path.basename(outputPath); 1954 var outFilename = path.basename(outputPath);
1938 var printer = new srcmaps.Printer(outFilename); 1955 var printer = new srcmaps.Printer(outFilename);
1939 _writeNode( 1956 _writeNode(new SourceMapPrintingContext(
1940 new SourceMapPrintingContext(printer, path.dirname(outputPath)), 1957 printer, path.dirname(outputPath)), jsTree);
1941 jsTree);
1942 printer.add('//# sourceMappingURL=$outFilename.map'); 1958 printer.add('//# sourceMappingURL=$outFilename.map');
1943 // Write output file and source map 1959 // Write output file and source map
1944 var text = printer.text; 1960 var text = printer.text;
1945 new File(outputPath).writeAsStringSync(text); 1961 new File(outputPath).writeAsStringSync(text);
1946 new File('$outputPath.map').writeAsStringSync(printer.map); 1962 new File('$outputPath.map').writeAsStringSync(printer.map);
1947 return computeHash(text); 1963 return computeHash(text);
1948 } else { 1964 } else {
1949 var text = jsNodeToString(jsTree); 1965 var text = jsNodeToString(jsTree);
1950 new File(outputPath).writeAsStringSync(text); 1966 new File(outputPath).writeAsStringSync(text);
1951 return computeHash(text); 1967 return computeHash(text);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2039 2055
2040 // TODO(jmesserly): in many cases marking the end will be unncessary. 2056 // TODO(jmesserly): in many cases marking the end will be unncessary.
2041 printer.mark(_location(node.end)); 2057 printer.mark(_location(node.end));
2042 } 2058 }
2043 2059
2044 String _getIdentifier(AstNode node) { 2060 String _getIdentifier(AstNode node) {
2045 if (node is SimpleIdentifier) return node.name; 2061 if (node is SimpleIdentifier) return node.name;
2046 return null; 2062 return null;
2047 } 2063 }
2048 } 2064 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698