Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 5 # BSD-style license that can be found in the LICENSE file. |
| 6 # | 6 # |
| 7 | 7 |
| 8 """ | 8 """ |
| 9 Generates an html file (frogpad.html) that can be used to execute the frog | 9 Frogpad is used to compile .dart files to javascript. |
| 10 compiler in a web browser or DumpRenderTree, | |
| 11 | 10 |
| 12 The generated frogpad.html will contain: | 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: | |
| 13 | 16 |
| 14 1. all the dart files that compose a dart program | 17 1. all the dart files that compose a dart program |
| 15 2. all the dart files of dart:core and other standard dart libraries | 18 2. all the dart files of dart:core and other standard dart libraries |
| 16 3. frogpad.dart (compiled to javascript) | 19 3. frogpad.dart (compiled to javascript) |
| 17 | 20 |
| 18 The contents of each dart file is placed in a separate <script> tag. | 21 The contents of each dart file is placed in a separate <script> tag. |
| 19 | 22 |
| 20 When the html page is loaded by a browser, the frog compiler will be invoked | 23 When the html page is loaded by a browser, the frog compiler is invoked |
| 21 and the user's dart program will be compiled to javascript. The generated | 24 and the dart program is compiled to javascript. The generated javascript is |
| 22 javascript will be placed in the <pre> element with id "output". | 25 placed in a <pre> element with id "output". |
| 23 | 26 |
| 24 If using DumpRenderTree, the output javascript can be obtained by dumping | 27 When the html page is passed to DumpRenderTree, the dumped output will |
| 25 the page as text and looking for the contents of the output textarea. | 28 have the generated javascript. |
| 26 """ | 29 """ |
| 27 | 30 |
| 28 import logging | 31 import logging |
| 29 import optparse | 32 import optparse |
| 30 import os.path | 33 import os.path |
| 31 import re | 34 import re |
| 32 import subprocess | 35 import subprocess |
| 33 import sys | 36 import sys |
| 34 | 37 |
| 38 | |
| 35 class FileNotFoundException(Exception): | 39 class FileNotFoundException(Exception): |
| 36 def __init__(self, file_name): | 40 def __init__(self, file_name): |
| 37 self._name = file_name | 41 self._name = file_name |
| 38 | 42 |
| 39 def __str__(self): | 43 def __str__(self): |
| 40 return self._name | 44 return self._name |
| 41 | 45 |
| 42 | 46 |
| 43 class CommandFailedException(Exception): | 47 class CommandFailedException(Exception): |
| 44 def __init__(self, message): | 48 def __init__(self, message): |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 <pre id="timing"></pre> | 95 <pre id="timing"></pre> |
| 92 <div class="label">Output:</div> | 96 <div class="label">Output:</div> |
| 93 <pre id="output"></pre> | 97 <pre id="output"></pre> |
| 94 <script type="text/javascript"> | 98 <script type="text/javascript"> |
| 95 {{FROGPAD_JS}} | 99 {{FROGPAD_JS}} |
| 96 </script> | 100 </script> |
| 97 </body> | 101 </body> |
| 98 </html> | 102 </html> |
| 99 """ | 103 """ |
| 100 | 104 |
| 105 # This finds everything after the word "Output:" in the html page. | |
| 106 # (Note, because the javascript we're fishing out spans multiple lines | |
| 107 # we need to use the DOTALL switch here.) | |
| 108 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:(.*)#EOF", re.DOTALL) | |
|
Siggi Cherem (dart-lang)
2012/02/23 20:57:23
possibly add a '\n' after ':' also?
| |
| 109 | |
| 101 # We use "application/inert" here to make the browser ignore the | 110 # We use "application/inert" here to make the browser ignore the |
| 102 # these script tags. (frogpad.dart will fish out the contents as needed.) | 111 # these script tags. (frogpad.dart will fish out the contents as needed.) |
| 103 # | 112 # |
| 104 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> | 113 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> |
| 105 {{contents}} | 114 {{contents}} |
| 106 </script> | 115 </script> |
| 107 """ | 116 """ |
| 108 | 117 |
| 109 # Regex that finds #import, #source and #native directives in .dart files. | 118 # Regex that finds #import, #source and #native directives in .dart files. |
| 110 # match.group(1) = "import", "source" or "native" | 119 # match.group(1) = "import", "source" or "native" |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 125 } | 134 } |
| 126 | 135 |
| 127 | 136 |
| 128 class Pad(object): | 137 class Pad(object): |
| 129 """ | 138 """ |
| 130 Accumulates all source files that are needed to compile a dart program, | 139 Accumulates all source files that are needed to compile a dart program, |
| 131 and places them in <script> tags on an html page. | 140 and places them in <script> tags on an html page. |
| 132 """ | 141 """ |
| 133 | 142 |
| 134 def __init__(self, argv): | 143 def __init__(self, argv): |
| 135 parser = optparse.OptionParser() | 144 parser = optparse.OptionParser(usage= |
| 145 "%prog [options] file_to_compile.dart" | |
| 146 ) | |
| 136 parser.add_option("-r", "--rebuild", action="store_true", | 147 parser.add_option("-r", "--rebuild", action="store_true", |
| 137 help="forces rebuild of frogpad_js") | 148 help="forces rebuild of the frogpad javascript") |
| 138 parser.add_option("-o", "--out", | 149 parser.add_option("-o", "--out", |
| 139 help="name of javascript output file") | 150 help="name of javascript output file") |
| 151 parser.add_option("-v", "--verbose", action="store_true", | |
| 152 help="more verbose logging") | |
| 140 (options, args) = parser.parse_args(argv) | 153 (options, args) = parser.parse_args(argv) |
| 141 | 154 |
| 155 log_level = logging.INFO | |
| 156 if options.verbose: | |
| 157 log_level = logging.DEBUG | |
| 158 logging.basicConfig(level=log_level) | |
| 159 | |
| 142 if len(args) < 2: | 160 if len(args) < 2: |
| 143 usage() | 161 parser.print_help() |
| 162 sys.exit(1) | |
| 144 | 163 |
| 145 self.main_file = os.path.abspath(args[1]) | 164 self.main_file = os.path.abspath(args[1]) |
| 146 | 165 |
| 147 # directory of this script | 166 # directory of this script |
| 148 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0])) | 167 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0])) |
| 149 | 168 |
| 150 # root of dart source repo | 169 # root of dart source repo |
| 151 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( | 170 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( |
| 152 self.frogpad_dir))) | 171 self.frogpad_dir))) |
| 153 | 172 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 if options.rebuild: | 207 if options.rebuild: |
| 189 self.build_frogpad_js() | 208 self.build_frogpad_js() |
| 190 | 209 |
| 191 self.load_libraries() | 210 self.load_libraries() |
| 192 self.load_file(self.main_file) | 211 self.load_file(self.main_file) |
| 193 | 212 |
| 194 html = self.generate_html() | 213 html = self.generate_html() |
| 195 write_file(self.html_file, html) | 214 write_file(self.html_file, html) |
| 196 | 215 |
| 197 js = self.generate_js() | 216 js = self.generate_js() |
| 198 logging.debug("found javascript in drt output (%d lines)", | |
| 199 len(js.splitlines())) | |
| 200 write_file(self.js_file, js) | 217 write_file(self.js_file, js) |
| 201 logging.info("generated '%s'", self.js_file) | 218 |
| 219 line_count = len(js.splitlines()) | |
| 220 logging.info("generated '%s' (%d lines)", self.js_file, line_count) | |
| 202 | 221 |
| 203 def build_frogpad_js(self): | 222 def build_frogpad_js(self): |
| 204 dart_vm = os.path.join(self.dart_dir, "out/Release_ia32/dart") | 223 dart_vm = os.path.join(self.dart_dir, "out/Release_ia32/dart") |
| 205 check_exists(dart_vm) | 224 check_exists(dart_vm) |
| 206 | 225 |
| 207 frogc_dart = os.path.join(self.frog_dir, "frogc.dart") | 226 frogc_dart = os.path.join(self.frog_dir, "frogc.dart") |
| 208 frogpad_dart = os.path.join(self.frogpad_dir, "frogpad.dart") | 227 frogpad_dart = os.path.join(self.frogpad_dir, "frogpad.dart") |
| 209 check_exists(frogc_dart) | 228 check_exists(frogc_dart) |
| 210 check_exists(frogpad_dart) | 229 check_exists(frogpad_dart) |
| 211 | 230 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 return html | 265 return html |
| 247 | 266 |
| 248 def generate_js(self): | 267 def generate_js(self): |
| 249 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree") | 268 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree") |
| 250 check_exists(drt) | 269 check_exists(drt) |
| 251 args = [] | 270 args = [] |
| 252 args.append(drt) | 271 args.append(drt) |
| 253 args.append(self.html_file) | 272 args.append(self.html_file) |
| 254 | 273 |
| 255 stdout = run_command(args) | 274 stdout = run_command(args) |
| 256 match = re.match("(?s).*Output:(.*)#EOF", stdout) | 275 match = OUTPUT_JAVASCRIPT_REGEX.match(stdout) |
| 257 if not match: | 276 if not match: |
| 258 raise Exception("can't find regex in DumpRenderTree output") | 277 raise Exception("can't find regex in DumpRenderTree output") |
| 259 return match.group(1) | 278 return match.group(1) |
| 260 | 279 |
| 261 @staticmethod | 280 @staticmethod |
| 262 def _create_tag(id, contents): | 281 def _create_tag(id, contents): |
| 263 s = SCRIPT_TAG | 282 s = SCRIPT_TAG |
| 264 s = s.replace("{{id}}", id) | 283 s = s.replace("{{id}}", id) |
| 284 # TODO(mattsh) - need to html escape here | |
| 265 s = s.replace("{{contents}}", contents) | 285 s = s.replace("{{contents}}", contents) |
| 266 return s | 286 return s |
| 267 | 287 |
| 268 def dart_library(self, name): | 288 def dart_library(self, name): |
| 269 path = DART_LIBRARIES[name] | 289 path = DART_LIBRARIES[name] |
| 270 if not path: | 290 if not path: |
| 271 raise Exception("unrecognized 'dart:%s'", name) | 291 raise Exception("unrecognized 'dart:%s'", name) |
| 272 return os.path.join(self.frog_dir, path) | 292 return os.path.join(self.frog_dir, path) |
| 273 | 293 |
| 274 def load_libraries(self): | 294 def load_libraries(self): |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 logging.info(level, '%s: %s', args[0], line) | 387 logging.info(level, '%s: %s', args[0], line) |
| 368 exitcode = child.wait() | 388 exitcode = child.wait() |
| 369 if exitcode: | 389 if exitcode: |
| 370 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command) | 390 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command) |
| 371 logging.error(msg) | 391 logging.error(msg) |
| 372 raise CommandFailedException(msg) | 392 raise CommandFailedException(msg) |
| 373 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) | 393 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) |
| 374 return stdout | 394 return stdout |
| 375 | 395 |
| 376 | 396 |
| 377 def usage(): | |
| 378 print(""" | |
| 379 Usage: | |
| 380 frogpad.py --out hello.js hello.dart | |
| 381 """) | |
| 382 sys.exit(1) | |
| 383 | |
| 384 | |
| 385 def main(argv): | 397 def main(argv): |
| 386 logging.basicConfig(level=logging.INFO) | |
| 387 Pad(argv) | 398 Pad(argv) |
| 388 | 399 |
| 389 if __name__ == "__main__": | 400 if __name__ == "__main__": |
| 390 sys.exit(main(sys.argv)) | 401 sys.exit(main(sys.argv)) |
| OLD | NEW |