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

Side by Side Diff: lib/src/template/compile.dart

Issue 11092092: Support compiling templates in the browser. Base URL: git@github.com:dart-lang/dart-web-components.git@master
Patch Set: Created 8 years, 2 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/template/analyzer.dart ('k') | lib/src/template/dartio_stub.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 compile; 5 library compile;
6 6
7 import 'dart:coreimpl'; 7 import 'dart:coreimpl';
8 import 'package:html5lib/dom.dart'; 8 import 'package:html5lib/dom.dart';
9 import 'package:html5lib/html5parser.dart'; 9 import 'package:html5lib/parser.dart';
10 import 'package:html5lib/tokenizer.dart';
11 10
12 import 'analyzer.dart'; 11 import 'analyzer.dart';
13 import 'code_printer.dart'; 12 import 'code_printer.dart';
14 import 'codegen.dart' as codegen; 13 import 'codegen.dart' as codegen;
15 import 'emitters.dart'; 14 import 'emitters.dart';
16 import 'file_system.dart'; 15 import 'file_system.dart';
17 import 'files.dart'; 16 import 'files.dart';
18 import 'info.dart'; 17 import 'info.dart';
19 import 'utils.dart'; 18 import 'utils.dart';
20 import 'world.dart'; 19 import 'world.dart';
21 20
22 // TODO(jmesserly): move these things into html5lib's public api 21 // TODO(jmesserly): move these things into html5lib's public api
23 // This is for voidElements: 22 // This is for voidElements:
24 import 'package:html5lib/src/constants.dart' as html5_constants; 23 import 'package:html5lib/src/constants.dart' as html5_constants;
25 // This is for htmlEscapeMinimal: 24 // This is for htmlEscapeMinimal:
26 import 'package:html5lib/src/utils.dart' as html5_utils; 25 import 'package:html5lib/src/utils.dart' as html5_utils;
27 26
28 27
29 Document parseHtml(String template, String sourcePath) { 28 Document parseHtml(String template, String sourcePath) {
30 var parser = new HTMLParser(); 29 var parser = new HtmlParser(template, generateSpans: true);
31 var document = parser.parse(new HTMLTokenizer(template)); 30 var document = parser.parse();
32 31
33 // Note: errors aren't fatal in HTML (unless strict mode is on). 32 // Note: errors aren't fatal in HTML (unless strict mode is on).
34 // So just print them as warnings. 33 // So just print them as warnings.
35 for (var e in parser.errors) { 34 for (var e in parser.errors) {
36 world.warning('$sourcePath line ${e.line}:${e.column}: ${e.message}'); 35 world.warning('$sourcePath line ${e.line}:${e.column}: ${e.message}');
37 } 36 }
38 return document; 37 return document;
39 } 38 }
40 39
41 /** 40 /**
42 * Walk the tree produced by the parser looking for templates, expressions, etc. 41 * Walk the tree produced by the parser looking for templates, expressions, etc.
43 * as a prelude to emitting the code for the template. 42 * as a prelude to emitting the code for the template.
44 */ 43 */
45 class Compile { 44 class Compile {
46 final FileSystem filesystem; 45 final FileSystem filesystem;
47 final List<SourceFile> files; 46 final List<SourceFile> files;
48 final List<OutputFile> output; 47 final List<OutputFile> output;
49 48
50 /** Information about source [files] given their href. */ 49 /** Information about source [files] given their href. */
51 final Map<String, FileInfo> info; 50 final Map<String, FileInfo> info;
52 51
53 /** Used by template tool to open a file. */ 52 /** Used by template tool to open a file. */
54 Compile(this.filesystem) 53 Compile(this.filesystem)
55 : files = <SourceFile>[], 54 : files = <SourceFile>[],
56 output = <OutputFile>[], 55 output = <OutputFile>[],
57 info = new SplayTreeMap<String, FileInfo>(); 56 info = new SplayTreeMap<String, FileInfo>();
58 57
59 /** Compile the application starting from the given [inputFile]. */ 58 /** Compile the application starting from the given [mainFile]. */
60 void run(String inputFile, [String baseDir = ""]) { 59 Future run(String mainFile, [String baseDir = ""]) {
61 _parseAndDiscover(inputFile, baseDir); 60 return _parseAndDiscover(mainFile, baseDir).transform((_) {
62 _analyze(); 61 _analyze();
63 _emit(); 62 _emit();
63 return null;
64 });
64 } 65 }
65 66
66 /** 67 /**
67 * Parse [inputFile] and recursively discover web components to load and 68 * Asynchronously parse [inputFile] and recursively discover web components to
68 * parse. 69 * load and parse. Returns a future that completes when all files are
70 * processed.
69 */ 71 */
70 void _parseAndDiscover(String inputFile, String baseDir) { 72 Future _parseAndDiscover(String inputFile, String baseDir) {
71 var pending = new Queue<String>(); // files to process 73 var pending = new Queue<String>(); // files to process
72 pending.addLast(inputFile);
73 while (!pending.isEmpty()) {
74 var filename = pending.removeFirst();
75 74
76 // Parse the file. 75 Completer done = new Completer();
77 if (info.containsKey(filename)) continue; 76 // We are not done until the number of in progress requests goes back to 0.
78 var file = _parseHtmlFile(filename, baseDir); 77 int inProgress = 0;
79 files.add(file);
80 78
81 // Find additional components being loaded. 79 notifyIfDone() {
82 var fileInfo = time('Analyzed definitions ${file.filename}', 80 assert(inProgress >= 0);
83 () => analyzeDefinitions(file, isEntryPoint: filename == inputFile)); 81 if (inProgress == 0) {
84 info[file.filename] = fileInfo; 82 done.complete(null);
85
86 for (var href in fileInfo.componentLinks) {
87 pending.addLast(href);
88 }
89
90 // Load .dart files being referenced in components.
91 for (var component in fileInfo.declaredComponents) {
92 var src = component.externalFile;
93 if (src != null) {
94 var dartFile = _parseDartFile(src, baseDir);
95 var fileInfo = new FileInfo(dartFile.filename);
96 info[dartFile.filename] = fileInfo;
97 fileInfo.userCode = dartFile.code;
98 files.add(dartFile);
99 }
100 } 83 }
101 } 84 }
85
86 pending.addLast(inputFile);
87
88 parsePending() {
89 while (!pending.isEmpty()) {
90 var filename = pending.removeFirst();
91
92 // Parse the file.
93 if (info.containsKey(filename)) continue;
94
95 inProgress++;
96
97 _parseHtmlFile(filename, baseDir).then((file) {
98 files.add(file);
99
100 // Find additional components being loaded.
101 var fileInfo = time('Analyzed definitions ${file.filename}',
102 () => analyzeDefinitions(
103 file, isEntryPoint: filename == inputFile));
104 info[file.filename] = fileInfo;
105 for (var href in fileInfo.componentLinks) {
106 pending.addLast(href);
107 }
108 // Load .dart files being referenced in components.
109 for (var component in fileInfo.declaredComponents) {
110 var src = component.externalFile;
111 if (src != null) {
112 inProgress++;
113 _parseDartFile(src, baseDir).then((dartFile) {
114 var fileInfo = new FileInfo(dartFile.filename);
115 info[dartFile.filename] = fileInfo;
116 fileInfo.userCode = dartFile.code;
117 files.add(dartFile);
118 inProgress--;
119 notifyIfDone();
120 });
121 }
122 }
123 inProgress--;
124 parsePending();
125 });
126 }
127 notifyIfDone();
128 }
129
130 parsePending();
131 return done.future;
102 } 132 }
103 133
104 /** Parse [filename]. */ 134 /** Asynchronously parse [filename]. */
105 SourceFile _parseHtmlFile(String filename, String baseDir) { 135 Future<SourceFile> _parseHtmlFile(String filename, String baseDir) {
106 var file = new SourceFile(filename); 136 return filesystem.readAll("$baseDir/$filename").transform(
107 var source = filesystem.readAll("$baseDir/$filename"); 137 (source) {
108 file.document = time("Parsed $filename", () => parseHtml(source, filename)); 138 var file = new SourceFile(filename);
109 if (options.dumpTree) { 139 file.document = time("Parsed $filename",
110 print("\n\n Dump Tree $filename:\n\n"); 140 () => parseHtml(source, filename));
111 print(file.document.outerHTML); 141 if (options.dumpTree) {
112 print("\n=========== End of AST ===========\n\n"); 142 print("\n\n Dump Tree $filename:\n\n");
113 } 143 print(file.document.outerHTML);
114 return file; 144 print("\n=========== End of AST ===========\n\n");
145 }
146 return file;
147 });
115 } 148 }
116 149
117 /** Parse [filename] and treat it as a .dart file. */ 150 /** Parse [filename] and treat it as a .dart file. */
118 SourceFile _parseDartFile(String filename, String baseDir) { 151 Future<SourceFile> _parseDartFile(String filename, String baseDir) {
119 var file = new SourceFile(filename, isDart: true); 152 return filesystem.readAll("$baseDir/$filename").transform((source) =>
120 file.code = time("Read $baseDir/$filename", 153 new SourceFile(filename, isDart: true)
121 () => filesystem.readAll("$baseDir/$filename")); 154 ..code = source);
122 return file;
123 } 155 }
124 156
125 /** Run the analyzer on every input html file. */ 157 /** Run the analyzer on every input html file. */
126 void _analyze() { 158 void _analyze() {
127 for (var file in files) { 159 for (var file in files) {
128 if (file.isDart) continue; 160 if (file.isDart) continue;
129 time('Analyzed contents ${file.filename}', () => analyzeFile(file, info)); 161 time('Analyzed contents ${file.filename}', () => analyzeFile(file, info));
130 } 162 }
131 } 163 }
132 164
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 if (doctype.tagName != 'html' || commentIndex != 1) { 280 if (doctype.tagName != 'html' || commentIndex != 1) {
249 world.warning('${file.filename}: file should start with <!DOCTYPE html> ' 281 world.warning('${file.filename}: file should start with <!DOCTYPE html> '
250 'to avoid the possibility of it being parsed in quirks mode in IE. ' 282 'to avoid the possibility of it being parsed in quirks mode in IE. '
251 'See http://www.w3.org/TR/html5-diff/#doctype'); 283 'See http://www.w3.org/TR/html5-diff/#doctype');
252 } 284 }
253 } 285 }
254 document.nodes.insertAt(commentIndex, parseFragment( 286 document.nodes.insertAt(commentIndex, parseFragment(
255 '\n<!-- This file was auto-generated from template ' 287 '\n<!-- This file was auto-generated from template '
256 '${file.filename}. -->\n')); 288 '${file.filename}. -->\n'));
257 } 289 }
OLDNEW
« no previous file with comments | « lib/src/template/analyzer.dart ('k') | lib/src/template/dartio_stub.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698