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

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

Issue 1788973002: Remove code that requires whole-program compile (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: merged Created 4 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
« no previous file with comments | « lib/src/codegen/code_generator.dart ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 'package:html/dom.dart'; 5 import 'package:html/dom.dart';
6 import 'package:html/parser.dart' show parseFragment; 6 import 'package:html/parser.dart' show parseFragment;
7 import 'package:logging/logging.dart' show Logger; 7 import 'package:logging/logging.dart' show Logger;
8 import 'package:path/path.dart' as path;
9
10 import '../compiler.dart' show AbstractCompiler;
11 import '../server/dependency_graph.dart';
12 import '../utils.dart' show colorOf, resourceOutputPath;
13
14 /// Emits an entry point HTML file corresponding to [inputFile] that can load
15 /// the code generated by the dev compiler.
16 ///
17 /// This internally transforms the given HTML [document]. When compiling to
18 /// JavaScript, we remove any Dart script tags, add new script tags to load our
19 /// runtime and the compiled code, and to execute the main method of the
20 /// application. When compiling to Dart, we ensure that the document contains a
21 /// single Dart script tag, but otherwise emit the original document
22 /// unmodified.
23 String generateEntryHtml(HtmlSourceNode root, AbstractCompiler compiler) {
24 var options = compiler.options;
25 var document = root.document.clone(true);
26 var scripts = document.querySelectorAll('script[type="application/dart"]');
27 if (scripts.isEmpty) {
28 _log.warning('No <script type="application/dart"> found in ${root.uri}');
29 // TODO(jacobr): we would rather return document.outerHtml to avoid future
30 // bugs that would only show up with html files include references to Dart
31 // scripts. Passing through the input content is needed to avoid breaking
32 // Angular ecause the spec-compliant HTML parser used modifies the HTML
33 // in a way that breaks Angular templates. An alternate fix would be to
34 // write an HTML emitter that preserves the structure of the input HTML as
35 // much as possible.
36 return root.contents;
37 }
38 scripts.skip(1).forEach((s) {
39 // TODO(sigmund): allow more than one Dart script tags?
40 _log.warning(s.sourceSpan.message(
41 'unexpected script. Only one Dart script tag allowed '
42 '(see https://github.com/dart-lang/dart-dev-compiler/issues/53).',
43 color: options.useColors ? colorOf('warning') : false));
44 s.remove();
45 });
46
47 var libraries = [];
48 var resources = new Set();
49 visitInPostOrder(root, (n) {
50 if (n is DartSourceNode) libraries.add(n);
51 if (n is ResourceSourceNode) resources.add(n);
52 }, includeParts: false);
53
54 root.htmlResourceNodes.forEach((element, resource) {
55 // Make sure we don't try and add this node again.
56 resources.remove(resource);
57
58 var resourcePath =
59 resourceOutputPath(resource.uri, root.uri, options.runtimeDir);
60 if (resource.cachingHash != null) {
61 resourcePath = _addHash(resourcePath, resource.cachingHash);
62 }
63 var attrs = element.attributes;
64 if (attrs.containsKey('href')) {
65 attrs['href'] = resourcePath;
66 } else if (attrs.containsKey('src')) {
67 attrs['src'] = resourcePath;
68 }
69 });
70
71 var rootDir = path.dirname(root.uri.path);
72 String rootRelative(String fullPath) {
73 return path.relative(path.join(compiler.inputBaseDir, fullPath),
74 from: rootDir);
75 }
76
77 var fragment = new DocumentFragment();
78 for (var resource in resources) {
79 var resourcePath = rootRelative(
80 resourceOutputPath(resource.uri, root.uri, options.runtimeDir));
81 var ext = path.extension(resourcePath);
82 if (resource.cachingHash != null) {
83 resourcePath = _addHash(resourcePath, resource.cachingHash);
84 }
85 if (ext == '.js') {
86 fragment.nodes.add(libraryInclude(resourcePath));
87 } else if (ext == '.css') {
88 var stylesheetLink = '<link rel="stylesheet" href="$resourcePath">\n';
89 fragment.nodes.add(parseFragment(stylesheetLink));
90 }
91 }
92
93 String mainLibraryName;
94 var src = scripts[0].attributes["src"];
95 var scriptUri = root.source.resolveRelativeUri(Uri.parse(src));
96
97 for (var lib in libraries) {
98 var info = lib.info;
99 if (info == null) continue;
100 var uri = info.library.source.uri;
101 var jsPath = rootRelative(compiler.getModulePath(uri));
102 if (uri == scriptUri) mainLibraryName = compiler.getModuleName(uri);
103 if (lib.cachingHash != null) {
104 jsPath = _addHash(jsPath, lib.cachingHash);
105 }
106 fragment.nodes.add(libraryInclude(jsPath));
107 }
108 fragment.nodes.add(invokeMain(mainLibraryName));
109 scripts[0].replaceWith(fragment);
110 return '${document.outerHtml}\n';
111 }
112 8
113 // TODO(jmesserly): the string interpolation in these could lead to injection 9 // TODO(jmesserly): the string interpolation in these could lead to injection
114 // bugs. Not really a security issue since input is trusted, but the resulting 10 // bugs. Not really a security issue since input is trusted, but the resulting
115 // parse tree may not match expectations if interpolated strings contain quotes. 11 // parse tree may not match expectations if interpolated strings contain quotes.
116 12
117 /// A script tag that loads the .js code for a compiled library. 13 /// A script tag that loads the .js code for a compiled library.
118 Node libraryInclude(String jsUrl) => 14 Node libraryInclude(String jsUrl) =>
119 parseFragment('<script src="$jsUrl"></script>\n'); 15 parseFragment('<script src="$jsUrl"></script>\n');
120 16
121 /// A script tag that invokes the main function on the entry point library. 17 /// A script tag that invokes the main function on the entry point library.
122 Node invokeMain(String mainLibraryName) { 18 Node invokeMain(String mainLibraryName) {
123 var code = mainLibraryName == null 19 var code = mainLibraryName == null
124 ? 'console.error("dev_compiler error: main was not generated");' 20 ? 'console.error("dev_compiler error: main was not generated");'
125 // TODO(vsm): Can we simplify this? 21 // TODO(vsm): Can we simplify this?
126 // See: https://github.com/dart-lang/dev_compiler/issues/164 22 // See: https://github.com/dart-lang/dev_compiler/issues/164
127 : "dart_library.start('$mainLibraryName');"; 23 : "dart_library.start('$mainLibraryName');";
128 return parseFragment('<script>$code</script>\n'); 24 return parseFragment('<script>$code</script>\n');
129 } 25 }
130 26
131 /// Convert the outputPath to include the hash in it. This function is the
132 /// reverse of what the server does to determine whether a request needs to have
133 /// cache headers added to it.
134 _addHash(String outPath, String hash) {
135 // (the ____ prefix makes it look better in the web inspector)
136 return '$outPath?____cached=$hash';
137 }
138
139 final _log = new Logger('dev_compiler.src.codegen.html_codegen'); 27 final _log = new Logger('dev_compiler.src.codegen.html_codegen');
OLDNEW
« no previous file with comments | « lib/src/codegen/code_generator.dart ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698