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

Side by Side Diff: tools/testing/frogpad/frogpad.py

Issue 10919138: Remove frogpad, as it's unused. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « tools/testing/frogpad/frogpad.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
4 # for details. All rights reserved. Use of this source code is governed by a
5 # BSD-style license that can be found in the LICENSE file.
6 #
7
8 """
9 Frogpad is used to compile .dart files to javascript.
10
11 This is accomplished by first creating an html file (usually called
12 <something>.frogpad.html) that can be used to execute the frog compiler in
13 a web browser (or DumpRenderTree).
14
15 The generated frogpad.html contains:
16
17 1. all the dart files that compose a dart program
18 2. all the dart files of dart:core and other standard dart libraries
19 3. frogpad.dart (compiled to javascript)
20
21 The contents of each dart file is placed in a separate <script> tag.
22
23 When the html page is loaded by a browser, the frog compiler is invoked
24 and the dart program is compiled to javascript. The generated javascript is
25 placed in a <pre> element with id "output".
26
27 When the html page is passed to DumpRenderTree, the dumped output will
28 have the generated javascript.
29 """
30
31 import logging
32 import optparse
33 import os.path
34 import platform
35 import re
36 import subprocess
37 import sys
38
39
40 class FileNotFoundException(Exception):
41 def __init__(self, file_name):
42 self._name = file_name
43
44 def __str__(self):
45 return self._name
46
47
48 class CommandFailedException(Exception):
49 def __init__(self, message):
50 self._message = message
51
52 def GetMessage(self):
53 return self._message
54
55
56 # Template for the html page we're going to generate.
57 HTML = """<!DOCTYPE html>
58 <html>
59 <head>
60 <style type="text/css">
61 textarea {
62 width: 100%;
63 height: 200px;
64 }
65 .label {
66 margin-top: 5px;
67 }
68 pre {
69 border: 2px solid black;
70 }
71 </style>
72 {{script_tags}}
73 <script type="text/javascript">
74 if (window.layoutTestController) {
75 layoutTestController.dumpAsText();
76 }
77 </script>
78 </head>
79 <body>
80 <h1>Frogpad</h1>
81 <div class="label">Input:</div>
82 <textarea id="input"></textarea>
83 <div class="label">Compiler Messages:</div>
84 <pre id="warnings"></pre>
85 <div class="label">Timing:</div>
86 <pre id="timing"></pre>
87 <div class="label">Output:</div>
88 <pre id="output"></pre>
89 <script type="text/javascript">
90 {{FROGPAD_JS}}
91 </script>
92 </body>
93 </html>
94 """
95
96 # This finds everything after the word "Output:" in the html page.
97 # (Note, because the javascript we're fishing out spans multiple lines
98 # we need to use the DOTALL switch here.)
99 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:\n(.*)\n#EOF", re.DOTALL)
100
101 # If the frogpad.dart encounters a compilation error, the generated
102 # javascript will start with the word 'throw'.
103 COMPILATION_ERROR_REGEX = re.compile(".*frogpad compilation error.*", re.DOTALL)
104
105 # We use "application/inert" here to make the browser ignore the
106 # these script tags. (frogpad.dart will fish out the contents as needed.)
107 #
108 SCRIPT_TAG = """<script type="application/inert" id="{{id}}">
109 {{contents}}
110 </script>
111 """
112
113 # Regex that finds #import, #source and #native directives in .dart files.
114 # match.group(1) = "import", "source" or "native"
115 # match.group(2) = url of file being imported
116 DIRECTIVE_RE = re.compile(r"^#(import|source|native)\([\"']([^\"']*)[\"']")
117
118 # id of script tag that holds name of the top dart file to be compiled,
119 # (This file name passed will be passed to the frog compiler by frogpad.dart.)
120 MAIN_ID = "main_id"
121
122 # id of the script tag that holds the name of the frog directory
123 FROGDIR_ID = "frogdir_id"
124
125 DART_LIBRARIES = {
126 "core": "lib/corelib.dart",
127 "coreimpl": "lib/corelib_impl.dart",
128 "dom": "../lib/dom/frog/dom_frog.dart",
129 "html": "../lib/html/frog/html_frog.dart",
130 "isolate": "../lib/isolate/isolate_frog.dart",
131 "json": "../lib/json/json_frog.dart"
132 }
133
134 class Pad(object):
135 """
136 Accumulates all source files that are needed to compile a dart program,
137 and places them in <script> tags on an html page.
138 """
139
140 def __init__(self, argv):
141 parser = optparse.OptionParser(usage=
142 "%prog [options] file_to_compile.dart"
143 )
144 parser.add_option("-f", "--frogpad_js",
145 help="location of frogpad.js file")
146 parser.add_option("-o", "--out",
147 help="name of javascript output file")
148 parser.add_option("-v", "--verbose", action="store_true",
149 help="more verbose logging")
150 (options, args) = parser.parse_args(argv)
151
152 log_level = logging.INFO
153 if options.verbose:
154 log_level = logging.DEBUG
155 logging.basicConfig(level=log_level)
156
157 if len(args) < 2:
158 parser.print_help()
159 sys.exit(1)
160
161 self.main_file = os.path.abspath(args[1])
162
163 # directory of this script
164 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0]))
165
166 # root of dart source repo
167 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname(
168 self.frogpad_dir)))
169
170 # directory of frog compiler source code
171 self.frog_dir = os.path.join(self.dart_dir, "frog")
172
173 logging.debug("dartdir_dir: '%s'" % self.dart_dir)
174 logging.debug("frog_dir: '%s'" % self.frog_dir)
175 logging.debug("frogpad_dir: '%s'" % self.frogpad_dir)
176
177 # location of frogpad.js
178 # (frogpad.js is generated by running frogsh_bootstrap_wrapper.py)
179 if not options.frogpad_js:
180 raise Exception("--frogpad_js is required")
181
182 if not os.path.exists(options.frogpad_js):
183 raise FileNotFoundException(options.frogpad_js)
184
185 self.frogpad_js = options.frogpad_js
186
187 if options.out:
188 # user has specified an output file name
189 self.js_file = os.path.abspath(options.out)
190 else:
191 # User didn't specify an output file, so use the input
192 # file name as the base of the output file name.
193 self.js_file = self.main_file + ".frogpad.js"
194
195 logging.debug("js_file: '%s" % self.js_file)
196
197 # this is the html file that we pass to DumpRenderTree
198 self.html_file = self.js_file + ".frogpad.html"
199 logging.debug("html_file: '%s'" % self.html_file)
200
201 # map from file name to File object (contains entries for all corelib
202 # and all other dart files needed to compile main_file)
203 self.name_to_file = {}
204
205 # map from script tag id to File object
206 self.id_to_file = {}
207
208 self.load_libraries()
209 self.load_file(self.main_file)
210
211 html = self.generate_html()
212 write_file(self.html_file, html)
213
214 js = self.generate_js()
215 write_file(self.js_file, js)
216
217 line_count = len(js.splitlines())
218 logging.debug("generated '%s' (%d lines)", self.js_file, line_count)
219
220 match = COMPILATION_ERROR_REGEX.match(js)
221 if match:
222 sys.exit(1)
223
224 def generate_html(self):
225 tags = []
226 for f in self.id_to_file.values():
227 tags.append(self._create_tag(f.id, f.contents))
228 tags.append(self._create_tag(MAIN_ID, self.main_file))
229 tags.append(self._create_tag(FROGDIR_ID, self.frog_dir))
230 html = HTML.replace("{{script_tags}}", "".join(tags))
231 html = html.replace("{{FROGPAD_JS}}", read_file(self.frogpad_js))
232 return html
233
234 def generate_js(self):
235 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree")
236 if platform.system() == 'Darwin':
237 drt += ".app"
238 elif platform.system() == 'Windows':
239 raise Exception("frogpad does not run on Windows")
240
241 check_exists(drt)
242 args = []
243 args.append(drt)
244 args.append(self.html_file)
245
246 stdout = run_command(args)
247 match = OUTPUT_JAVASCRIPT_REGEX.match(stdout)
248 if not match:
249 raise Exception("can't find regex in DumpRenderTree output")
250 return match.group(1)
251
252 @staticmethod
253 def _create_tag(id, contents):
254 s = SCRIPT_TAG
255 s = s.replace("{{id}}", id)
256 # TODO(mattsh) - need to html escape here
257 s = s.replace("{{contents}}", contents)
258 return s
259
260 def dart_library(self, name):
261 path = DART_LIBRARIES[name]
262 if not path:
263 raise Exception("unrecognized 'dart:%s'", name)
264 return os.path.join(self.frog_dir, path)
265
266 def load_libraries(self):
267 for name in DART_LIBRARIES:
268 self.load_file(self.dart_library(name))
269
270 def load_file(self, name):
271 name = os.path.abspath(name)
272 if name in self.name_to_file:
273 return
274 f = File(self, name)
275 self.name_to_file[f.name] = f
276 if f.id in self.id_to_file:
277 raise Exception("ambiguous id '%s'" % f.id)
278 self.id_to_file[f.id] = f
279 f.directives()
280
281 class File(object):
282 def __init__(self, pad, name):
283 self.pad = pad
284 self.name = name
285 self.id = self._make_id()
286 check_exists(name)
287 with open(self.name, "r") as f:
288 self.contents = f.read()
289
290 def _make_id(self):
291 """
292 Generates an id (based on the file name) for the <script> tag that will
293 hold the contents of this file.
294 """
295 return self.name.replace("/", "_").replace(".", "_")
296
297 def directives(self):
298 """Load files referenced by #source, #import and #native directives."""
299 lines = self.contents.split("\n")
300 self.line_number = 0
301 for line in lines:
302 self.line_number += 1
303 self._directive(line)
304
305 def _directive(self, line):
306 match = DIRECTIVE_RE.match(line)
307 if not match:
308 return
309 url = match.group(2)
310 if url.startswith("dart:"):
311 path = self.pad.dart_library(url[len("dart:"):])
312 else:
313 path = os.path.join(os.path.dirname(self.name), url)
314 self.pad.load_file(path)
315
316 def read_file(file_name):
317 check_exists(file_name)
318 with open(file_name, "r") as input:
319 contents = input.read()
320 logging.debug("read_file '%s' (%d bytes)" % (file_name, len(contents)))
321 return contents
322
323 def write_file(file_name, contents):
324 with open(file_name, "w") as output:
325 output.write(contents)
326
327 check_exists(file_name)
328 logging.debug("write_file '%s' (%d bytes)" % (file_name, len(contents)))
329
330
331 def check_exists(file_name):
332 if not os.path.exists(file_name):
333 raise FileNotFoundException(file_name)
334
335
336 def format_command(args):
337 return ' '.join(args)
338
339
340 def run_command(args):
341 """
342 Args:
343 command: comamnd with arguments to exec
344 Returns:
345 all output that this command sent to stdout
346 """
347
348 command = format_command(args)
349 logging.info("RUNNING: '%s'" % command)
350 child = subprocess.Popen(args,
351 stdout=subprocess.PIPE,
352 stderr=subprocess.PIPE,
353 close_fds=True)
354 (stdout, stderr) = child.communicate()
355 exit_code = child.wait()
356 if exit_code:
357 for line in stderr.splitlines():
358 logging.info(line)
359 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command)
360 logging.error(msg)
361 raise CommandFailedException(msg)
362 logging.debug("SUCCEEDED (%d bytes)" % len(stdout))
363 return stdout
364
365
366 def main(argv):
367 Pad(argv)
368
369 if __name__ == "__main__":
370 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « tools/testing/frogpad/frogpad.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698