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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 <div class="label">Timing:</div> | 94 <div class="label">Timing:</div> |
| 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 |
|
Emily Fortuna
2012/02/23 17:05:10
Extra line?
mattsh
2012/02/23 17:27:09
Done.
| |
| 105 | |
| 106 # This finds everything after the word "Output:" in the html page. | |
| 107 # (Note, because the javascript we're fishing out spans multiple lines | |
| 108 # we need to use the DOTALL switch here.) | |
| 109 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*Output:(.*)#EOF", re.DOTALL) | |
| 110 | |
| 111 | |
| 101 # We use "application/inert" here to make the browser ignore the | 112 # We use "application/inert" here to make the browser ignore the |
| 102 # these script tags. (frogpad.dart will fish out the contents as needed.) | 113 # these script tags. (frogpad.dart will fish out the contents as needed.) |
| 103 # | 114 # |
| 104 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> | 115 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> |
| 105 {{contents}} | 116 {{contents}} |
| 106 </script> | 117 </script> |
| 107 """ | 118 """ |
| 108 | 119 |
| 109 # Regex that finds #import, #source and #native directives in .dart files. | 120 # Regex that finds #import, #source and #native directives in .dart files. |
| 110 # match.group(1) = "import", "source" or "native" | 121 # match.group(1) = "import", "source" or "native" |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 125 } | 136 } |
| 126 | 137 |
| 127 | 138 |
| 128 class Pad(object): | 139 class Pad(object): |
| 129 """ | 140 """ |
| 130 Accumulates all source files that are needed to compile a dart program, | 141 Accumulates all source files that are needed to compile a dart program, |
| 131 and places them in <script> tags on an html page. | 142 and places them in <script> tags on an html page. |
| 132 """ | 143 """ |
| 133 | 144 |
| 134 def __init__(self, argv): | 145 def __init__(self, argv): |
| 135 parser = optparse.OptionParser() | 146 parser = optparse.OptionParser(usage= |
| 147 "%prog [options] file_to_compile.dart" | |
| 148 ) | |
| 136 parser.add_option("-r", "--rebuild", action="store_true", | 149 parser.add_option("-r", "--rebuild", action="store_true", |
| 137 help="forces rebuild of frogpad_js") | 150 help="forces rebuild of the frogpad javascript") |
| 138 parser.add_option("-o", "--out", | 151 parser.add_option("-o", "--out", |
| 139 help="name of javascript output file") | 152 help="name of javascript output file") |
| 153 parser.add_option("-v", "--verbose", | |
| 154 help="more verbose logging") | |
| 140 (options, args) = parser.parse_args(argv) | 155 (options, args) = parser.parse_args(argv) |
| 141 | 156 |
| 157 log_level = logging.INFO | |
| 158 if options.verbose: | |
| 159 log_level = logging.DEBUG | |
| 160 logging.basicConfig(level=log_level) | |
| 161 | |
| 142 if len(args) < 2: | 162 if len(args) < 2: |
| 143 usage() | 163 parser.print_help() |
| 164 sys.exit(1) | |
| 144 | 165 |
| 145 self.main_file = os.path.abspath(args[1]) | 166 self.main_file = os.path.abspath(args[1]) |
| 146 | 167 |
| 147 # directory of this script | 168 # directory of this script |
| 148 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0])) | 169 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0])) |
| 149 | 170 |
| 150 # root of dart source repo | 171 # root of dart source repo |
| 151 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( | 172 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( |
| 152 self.frogpad_dir))) | 173 self.frogpad_dir))) |
| 153 | 174 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 return html | 267 return html |
| 247 | 268 |
| 248 def generate_js(self): | 269 def generate_js(self): |
| 249 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree") | 270 drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree") |
| 250 check_exists(drt) | 271 check_exists(drt) |
| 251 args = [] | 272 args = [] |
| 252 args.append(drt) | 273 args.append(drt) |
| 253 args.append(self.html_file) | 274 args.append(self.html_file) |
| 254 | 275 |
| 255 stdout = run_command(args) | 276 stdout = run_command(args) |
| 256 match = re.match("(?s).*Output:(.*)#EOF", stdout) | 277 match = OUTPUT_JAVASCRIPT_REGEX.match(stdout) |
| 257 if not match: | 278 if not match: |
| 258 raise Exception("can't find regex in DumpRenderTree output") | 279 raise Exception("can't find regex in DumpRenderTree output") |
| 259 return match.group(1) | 280 return match.group(1) |
| 260 | 281 |
| 261 @staticmethod | 282 @staticmethod |
| 262 def _create_tag(id, contents): | 283 def _create_tag(id, contents): |
| 263 s = SCRIPT_TAG | 284 s = SCRIPT_TAG |
| 264 s = s.replace("{{id}}", id) | 285 s = s.replace("{{id}}", id) |
| 286 # TODO(mattsh) - need to html escape here | |
| 265 s = s.replace("{{contents}}", contents) | 287 s = s.replace("{{contents}}", contents) |
| 266 return s | 288 return s |
| 267 | 289 |
| 268 def dart_library(self, name): | 290 def dart_library(self, name): |
| 269 path = DART_LIBRARIES[name] | 291 path = DART_LIBRARIES[name] |
| 270 if not path: | 292 if not path: |
| 271 raise Exception("unrecognized 'dart:%s'", name) | 293 raise Exception("unrecognized 'dart:%s'", name) |
| 272 return os.path.join(self.frog_dir, path) | 294 return os.path.join(self.frog_dir, path) |
| 273 | 295 |
| 274 def load_libraries(self): | 296 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) | 389 logging.info(level, '%s: %s', args[0], line) |
| 368 exitcode = child.wait() | 390 exitcode = child.wait() |
| 369 if exitcode: | 391 if exitcode: |
| 370 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command) | 392 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command) |
| 371 logging.error(msg) | 393 logging.error(msg) |
| 372 raise CommandFailedException(msg) | 394 raise CommandFailedException(msg) |
| 373 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) | 395 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) |
| 374 return stdout | 396 return stdout |
| 375 | 397 |
| 376 | 398 |
| 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): | 399 def main(argv): |
| 386 logging.basicConfig(level=logging.INFO) | |
| 387 Pad(argv) | 400 Pad(argv) |
| 388 | 401 |
| 389 if __name__ == "__main__": | 402 if __name__ == "__main__": |
| 390 sys.exit(main(sys.argv)) | 403 sys.exit(main(sys.argv)) |
| OLD | NEW |