| 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; | 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 final _properties = <FunctionDeclaration>[]; | 51 final _properties = <FunctionDeclaration>[]; |
| 52 final _privateNames = new HashSet<String>(); | 52 final _privateNames = new HashSet<String>(); |
| 53 final _pendingPrivateNames = <String>[]; | 53 final _pendingPrivateNames = <String>[]; |
| 54 | 54 |
| 55 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) | 55 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) |
| 56 : libraryInfo = libraryInfo, | 56 : libraryInfo = libraryInfo, |
| 57 rules = rules; | 57 rules = rules; |
| 58 | 58 |
| 59 Element get currentLibrary => libraryInfo.library; | 59 Element get currentLibrary => libraryInfo.library; |
| 60 | 60 |
| 61 JS.Block generateLibrary( | 61 JS.Program generateLibrary( |
| 62 Iterable<CompilationUnit> units, CheckerReporter reporter) { | 62 Iterable<CompilationUnit> units, CheckerReporter reporter) { |
| 63 var body = <JS.Statement>[]; | 63 var body = <JS.Statement>[]; |
| 64 for (var unit in units) { | 64 for (var unit in units) { |
| 65 // TODO(jmesserly): this is needed because RestrictedTypeRules can send | 65 // TODO(jmesserly): this is needed because RestrictedTypeRules can send |
| 66 // messages to CheckerReporter, for things like missing types. | 66 // messages to CheckerReporter, for things like missing types. |
| 67 // We should probably refactor so this can't happen. | 67 // We should probably refactor so this can't happen. |
| 68 var source = unit.element.source; | 68 var source = unit.element.source; |
| 69 _constEvaluator = new ConstantEvaluator(source, rules.provider); | 69 _constEvaluator = new ConstantEvaluator(source, rules.provider); |
| 70 reporter.enterSource(source); | 70 reporter.enterSource(source); |
| 71 body.add(_visit(unit)); | 71 body.add(_visit(unit)); |
| 72 reporter.leaveSource(); | 72 reporter.leaveSource(); |
| 73 } | 73 } |
| 74 | 74 |
| 75 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); | 75 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); |
| 76 | 76 |
| 77 // TODO(jmesserly): make these immutable in JS? | 77 // TODO(jmesserly): make these immutable in JS? |
| 78 for (var name in _exports) { | 78 for (var name in _exports) { |
| 79 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); | 79 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); |
| 80 } | 80 } |
| 81 | 81 |
| 82 var name = jsLibraryName(libraryInfo.library); | 82 var name = jsLibraryName(libraryInfo.library); |
| 83 return new JS.Block([ | 83 return new JS.Program([ |
| 84 js.statement('var #;', name), | 84 js.statement('var #;', name), |
| 85 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = {}));", | 85 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = {}));", |
| 86 [body, name, name]) | 86 [body, name, name]) |
| 87 ]); | 87 ]); |
| 88 } | 88 } |
| 89 | 89 |
| 90 JS.Statement _initPrivateSymbol(String name) => | 90 JS.Statement _initPrivateSymbol(String name) => |
| 91 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); | 91 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); |
| 92 | 92 |
| 93 @override | 93 @override |
| (...skipping 1826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 } | 1920 } |
| 1921 | 1921 |
| 1922 class JSGenerator extends CodeGenerator { | 1922 class JSGenerator extends CodeGenerator { |
| 1923 final JSCodeOptions options; | 1923 final JSCodeOptions options; |
| 1924 | 1924 |
| 1925 JSGenerator(String outDir, Uri root, TypeRules rules, this.options) | 1925 JSGenerator(String outDir, Uri root, TypeRules rules, this.options) |
| 1926 : super(outDir, root, rules); | 1926 : super(outDir, root, rules); |
| 1927 | 1927 |
| 1928 void generateLibrary(Iterable<CompilationUnit> units, LibraryInfo info, | 1928 void generateLibrary(Iterable<CompilationUnit> units, LibraryInfo info, |
| 1929 CheckerReporter reporter) { | 1929 CheckerReporter reporter) { |
| 1930 JS.Block jsTree = | 1930 JS.Program jsTree = |
| 1931 new JSCodegenVisitor(info, rules).generateLibrary(units, reporter); | 1931 new JSCodegenVisitor(info, rules).generateLibrary(units, reporter); |
| 1932 | 1932 |
| 1933 var outputPath = path.join(outDir, jsOutputPath(info, root)); | 1933 var outputPath = path.join(outDir, jsOutputPath(info, root)); |
| 1934 new Directory(path.dirname(outputPath)).createSync(recursive: true); | 1934 new Directory(path.dirname(outputPath)).createSync(recursive: true); |
| 1935 | 1935 |
| 1936 if (options.emitSourceMaps) { | 1936 if (options.emitSourceMaps) { |
| 1937 var outFilename = path.basename(outputPath); | 1937 var outFilename = path.basename(outputPath); |
| 1938 var printer = new srcmaps.Printer(outFilename); | 1938 var printer = new srcmaps.Printer(outFilename); |
| 1939 var context = | 1939 _writeNode( |
| 1940 new SourceMapPrintingContext(printer, path.dirname(outputPath)); | 1940 new SourceMapPrintingContext(printer, path.dirname(outputPath)), |
| 1941 _writeLibrary(context, jsTree); | 1941 jsTree); |
| 1942 printer.add('//# sourceMappingURL=$outFilename.map'); | 1942 printer.add('//# sourceMappingURL=$outFilename.map'); |
| 1943 // Write output file and source map | 1943 // Write output file and source map |
| 1944 new File(outputPath).writeAsStringSync(printer.text); | 1944 new File(outputPath).writeAsStringSync(printer.text); |
| 1945 new File('$outputPath.map').writeAsStringSync(printer.map); | 1945 new File('$outputPath.map').writeAsStringSync(printer.map); |
| 1946 } else { | 1946 } else { |
| 1947 var context = new JS.SimpleJavaScriptPrintingContext(); | 1947 new File(outputPath).writeAsStringSync(jsNodeToString(jsTree)); |
| 1948 _writeLibrary(context, jsTree); | |
| 1949 // Write output file and source map | |
| 1950 new File(outputPath).writeAsStringSync(context.getText()); | |
| 1951 } | 1948 } |
| 1952 } | 1949 } |
| 1953 | |
| 1954 void _writeLibrary(JS.JavaScriptPrintingContext context, JS.Block jsTree) { | |
| 1955 var opts = | |
| 1956 new JS.JavaScriptPrintingOptions(avoidKeywordsInIdentifiers: true); | |
| 1957 new JS.Printer(opts, context).blockOutWithoutBraces(jsTree); | |
| 1958 } | |
| 1959 } | 1950 } |
| 1960 | 1951 |
| 1952 void _writeNode(JS.JavaScriptPrintingContext context, JS.Node node) { |
| 1953 var opts = new JS.JavaScriptPrintingOptions(avoidKeywordsInIdentifiers: true); |
| 1954 node.accept(new JS.Printer(opts, context)); |
| 1955 } |
| 1956 |
| 1961 /// This is a debugging helper to print a JS node. | 1957 /// This is a debugging helper to print a JS node. |
| 1962 String debugJsNodeToString(JS.Node node) { | 1958 String jsNodeToString(JS.Node node) { |
| 1963 var context = new JS.SimpleJavaScriptPrintingContext(); | 1959 var context = new JS.SimpleJavaScriptPrintingContext(); |
| 1964 var opts = new JS.JavaScriptPrintingOptions(avoidKeywordsInIdentifiers: true); | 1960 _writeNode(context, node); |
| 1965 new JS.Printer(opts, context).visit(node); | |
| 1966 // Write output file and source map | |
| 1967 return context.getText(); | 1961 return context.getText(); |
| 1968 } | 1962 } |
| 1969 | 1963 |
| 1970 /// Choose a canonical name from the library element. | 1964 /// Choose a canonical name from the library element. |
| 1971 /// This never uses the library's name (the identifier in the `library` | 1965 /// This never uses the library's name (the identifier in the `library` |
| 1972 /// declaration) as it doesn't have any meaningful rules enforced. | 1966 /// declaration) as it doesn't have any meaningful rules enforced. |
| 1973 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 1967 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
| 1974 | 1968 |
| 1975 /// Path to file that will be generated for [info]. In case it's url is a | 1969 /// Path to file that will be generated for [info]. In case it's url is a |
| 1976 /// `file:` url, we use [root] to determine the relative path from the entry | 1970 /// `file:` url, we use [root] to determine the relative path from the entry |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2041 | 2035 |
| 2042 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2036 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2043 printer.mark(_location(node.end)); | 2037 printer.mark(_location(node.end)); |
| 2044 } | 2038 } |
| 2045 | 2039 |
| 2046 String _getIdentifier(AstNode node) { | 2040 String _getIdentifier(AstNode node) { |
| 2047 if (node is SimpleIdentifier) return node.name; | 2041 if (node is SimpleIdentifier) return node.name; |
| 2048 return null; | 2042 return null; |
| 2049 } | 2043 } |
| 2050 } | 2044 } |
| OLD | NEW |