| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 Google Inc. All rights reserved. | 2 # Copyright (c) 2012 Google Inc. All rights reserved. |
| 3 # | 3 # |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 import os | 30 import os |
| 31 import os.path as path | 31 import os.path as path |
| 32 import generate_protocol_externs | 32 import generate_protocol_externs |
| 33 import modular_build |
| 33 import re | 34 import re |
| 34 import shutil | 35 import shutil |
| 35 import subprocess | 36 import subprocess |
| 36 import sys | 37 import sys |
| 37 import tempfile | 38 import tempfile |
| 38 try: | 39 try: |
| 39 import simplejson as json | 40 import simplejson as json |
| 40 except ImportError: | 41 except ImportError: |
| 41 import json | 42 import json |
| 42 | 43 |
| 43 scripts_path = path.dirname(path.abspath(__file__)) | 44 scripts_path = path.dirname(path.abspath(__file__)) |
| 44 devtools_path = path.dirname(scripts_path) | 45 devtools_path = path.dirname(scripts_path) |
| 45 inspector_path = path.join(path.dirname(devtools_path), "core", "inspector") | 46 inspector_path = path.join(path.dirname(devtools_path), "core", "inspector") |
| 46 devtools_frontend_path = path.join(devtools_path, "front_end") | 47 devtools_frontend_path = path.join(devtools_path, "front_end") |
| 47 global_externs_file = path.join(devtools_frontend_path, "externs.js") | 48 global_externs_file = path.join(devtools_frontend_path, "externs.js") |
| 48 protocol_externs_file = path.join(devtools_frontend_path, "protocol_externs.js") | 49 protocol_externs_file = path.join(devtools_frontend_path, "protocol_externs.js") |
| 49 webgl_rendering_context_idl_path = path.join(path.dirname(devtools_path), "core"
, "html", "canvas", "WebGLRenderingContextBase.idl") | 50 webgl_rendering_context_idl_path = path.join(path.dirname(devtools_path), "core"
, "html", "canvas", "WebGLRenderingContextBase.idl") |
| 50 injected_script_source_name = path.join(inspector_path, "InjectedScriptSource.js
") | 51 injected_script_source_name = path.join(inspector_path, "InjectedScriptSource.js
") |
| 51 canvas_injected_script_source_name = path.join(inspector_path, "InjectedScriptCa
nvasModuleSource.js") | 52 canvas_injected_script_source_name = path.join(inspector_path, "InjectedScriptCa
nvasModuleSource.js") |
| 52 closure_compiler_jar = path.join(scripts_path, "closure", "compiler.jar") | 53 closure_compiler_jar = path.join(scripts_path, "closure", "compiler.jar") |
| 53 closure_runner_jar = path.join(scripts_path, "compiler-runner", "closure-runner.
jar") | 54 closure_runner_jar = path.join(scripts_path, "compiler-runner", "closure-runner.
jar") |
| 54 jsdoc_validator_jar = path.join(scripts_path, "jsdoc-validator", "jsdoc-validato
r.jar") | 55 jsdoc_validator_jar = path.join(scripts_path, "jsdoc-validator", "jsdoc-validato
r.jar") |
| 55 java_exec = "java -Xms1024m -server -XX:+TieredCompilation" | 56 java_exec = "java -Xms1024m -server -XX:+TieredCompilation" |
| 56 | 57 |
| 57 generate_protocol_externs.generate_protocol_externs(protocol_externs_file, path.
join(devtools_path, "protocol.json")) | 58 generate_protocol_externs.generate_protocol_externs(protocol_externs_file, path.
join(devtools_path, "protocol.json")) |
| 58 | 59 |
| 59 jsmodule_name_prefix = "jsmodule_" | 60 jsmodule_name_prefix = "jsmodule_" |
| 60 frontend_modules_name = "frontend_modules.json" | |
| 61 runtime_module_name = "_runtime" | 61 runtime_module_name = "_runtime" |
| 62 module_initializer_name = "_module.js" | 62 module_initializer_name = "_module.js" |
| 63 | 63 |
| 64 | 64 |
| 65 def log_error(message): | 65 def log_error(message): |
| 66 print "ERROR: " + message | 66 print "ERROR: " + message |
| 67 | 67 |
| 68 | 68 |
| 69 def error_excepthook(exctype, value, traceback): | 69 def error_excepthook(exctype, value, traceback): |
| 70 print "ERROR:" | 70 print "ERROR:" |
| 71 sys.__excepthook__(exctype, value, traceback) | 71 sys.__excepthook__(exctype, value, traceback) |
| 72 sys.excepthook = error_excepthook | 72 sys.excepthook = error_excepthook |
| 73 | 73 |
| 74 try: | 74 |
| 75 with open(path.join(scripts_path, frontend_modules_name), "rt") as js_module
s_file: | 75 loader = modular_build.DescriptorLoader(devtools_frontend_path) |
| 76 modules = json.loads(js_modules_file.read()) | 76 descriptors = loader.load_application('devtools.json') |
| 77 except: | 77 modules_by_name = descriptors.modules |
| 78 log_error("Failed to read %s" % frontend_modules_name) | |
| 79 raise | |
| 80 | 78 |
| 81 type_checked_jsdoc_tags_list = ["param", "return", "type", "enum"] | 79 type_checked_jsdoc_tags_list = ["param", "return", "type", "enum"] |
| 82 | 80 |
| 83 type_checked_jsdoc_tags_or = "|".join(type_checked_jsdoc_tags_list) | 81 type_checked_jsdoc_tags_or = "|".join(type_checked_jsdoc_tags_list) |
| 84 | 82 |
| 85 # Basic regex for invalid JsDoc types: an object type name ([A-Z][A-Za-z0-9.]+[A
-Za-z0-9]) not preceded by '!', '?', ':' (this, new), or '.' (object property). | 83 # Basic regex for invalid JsDoc types: an object type name ([A-Z][A-Za-z0-9.]+[A
-Za-z0-9]) not preceded by '!', '?', ':' (this, new), or '.' (object property). |
| 86 invalid_type_regex = re.compile(r"@(?:" + type_checked_jsdoc_tags_or + r")\s*\{.
*(?<![!?:.A-Za-z0-9])([A-Z][A-Za-z0-9.]+[A-Za-z0-9])[^/]*\}") | 84 invalid_type_regex = re.compile(r"@(?:" + type_checked_jsdoc_tags_or + r")\s*\{.
*(?<![!?:.A-Za-z0-9])([A-Z][A-Za-z0-9.]+[A-Za-z0-9])[^/]*\}") |
| 87 | 85 |
| 88 invalid_type_designator_regex = re.compile(r"@(?:" + type_checked_jsdoc_tags_or
+ r")\s*.*(?<![{: ])([?!])=?\}") | 86 invalid_type_designator_regex = re.compile(r"@(?:" + type_checked_jsdoc_tags_or
+ r")\s*.*(?<![{: ])([?!])=?\}") |
| 89 | 87 |
| 90 error_warning_regex = re.compile(r"(?:WARNING|ERROR)") | 88 error_warning_regex = re.compile(r"(?:WARNING|ERROR)") |
| 91 | 89 |
| 92 errors_found = False | 90 errors_found = False |
| 93 | 91 |
| 94 | 92 |
| 95 def run_in_shell(command_line): | 93 def run_in_shell(command_line): |
| 96 return subprocess.Popen(command_line, stdout=subprocess.PIPE, stderr=subproc
ess.STDOUT, shell=True) | 94 return subprocess.Popen(command_line, stdout=subprocess.PIPE, stderr=subproc
ess.STDOUT, shell=True) |
| 97 | 95 |
| 98 | 96 |
| 99 def hasErrors(output): | 97 def hasErrors(output): |
| 100 return re.search(error_warning_regex, output) != None | 98 return re.search(error_warning_regex, output) != None |
| 101 | 99 |
| 102 | 100 |
| 103 def dump_all_checked_files(): | |
| 104 files = {} | |
| 105 for module in modules: | |
| 106 for source in module["sources"]: | |
| 107 files[path.join(devtools_frontend_path, source)] = True | |
| 108 return files.keys() | |
| 109 | |
| 110 | |
| 111 def verify_jsdoc_extra(additional_files): | 101 def verify_jsdoc_extra(additional_files): |
| 112 return run_in_shell("%s -jar %s %s" % (java_exec, jsdoc_validator_jar, " ".j
oin(dump_all_checked_files() + additional_files))) | 102 return run_in_shell("%s -jar %s %s" % (java_exec, jsdoc_validator_jar, " ".j
oin(descriptors.all_compiled_files() + additional_files))) |
| 113 | 103 |
| 114 | 104 |
| 115 def verify_jsdoc(additional_files): | 105 def verify_jsdoc(additional_files): |
| 116 def file_list(): | 106 def file_list(): |
| 117 result = [] | 107 return descriptors.all_compiled_files() + additional_files |
| 118 for module in modules: | |
| 119 for file_name in module["sources"]: | |
| 120 result.append(path.join(devtools_frontend_path, file_name)) | |
| 121 for file in additional_files: | |
| 122 result.append(file) | |
| 123 return result | |
| 124 | 108 |
| 125 errors_found = False | 109 errors_found = False |
| 126 for full_file_name in file_list(): | 110 for full_file_name in file_list(): |
| 127 lineIndex = 0 | 111 lineIndex = 0 |
| 128 with open(full_file_name, "r") as sourceFile: | 112 with open(full_file_name, "r") as sourceFile: |
| 129 for line in sourceFile: | 113 for line in sourceFile: |
| 130 line = line.rstrip() | 114 line = line.rstrip() |
| 131 lineIndex += 1 | 115 lineIndex += 1 |
| 132 if not line: | 116 if not line: |
| 133 continue | 117 continue |
| (...skipping 28 matching lines...) Expand all Loading... |
| 162 sys.exit(1) | 146 sys.exit(1) |
| 163 print "Java executable: " + re.sub(r"\n$", "", javaPath) | 147 print "Java executable: " + re.sub(r"\n$", "", javaPath) |
| 164 | 148 |
| 165 check_java_path() | 149 check_java_path() |
| 166 | 150 |
| 167 modules_dir = tempfile.mkdtemp() | 151 modules_dir = tempfile.mkdtemp() |
| 168 common_closure_args = " --summary_detail_level 3 --jscomp_error visibility --com
pilation_level SIMPLE_OPTIMIZATIONS --warning_level VERBOSE --language_in ECMASC
RIPT5 --accept_const_keyword --module_output_path_prefix %s/" % modules_dir | 152 common_closure_args = " --summary_detail_level 3 --jscomp_error visibility --com
pilation_level SIMPLE_OPTIMIZATIONS --warning_level VERBOSE --language_in ECMASC
RIPT5 --accept_const_keyword --module_output_path_prefix %s/" % modules_dir |
| 169 | 153 |
| 170 spawned_compiler_command = "%s -jar %s %s \\\n" % (java_exec, closure_compiler_j
ar, common_closure_args) | 154 spawned_compiler_command = "%s -jar %s %s \\\n" % (java_exec, closure_compiler_j
ar, common_closure_args) |
| 171 | 155 |
| 172 modules_by_name = {} | |
| 173 standalone_modules_by_name = {} | 156 standalone_modules_by_name = {} |
| 174 dependents_by_module_name = {} | 157 dependents_by_module_name = {} |
| 175 | 158 |
| 176 for module in modules: | 159 for name in modules_by_name: |
| 177 name = module["name"] | 160 module = modules_by_name[name] |
| 178 modules_by_name[name] = module | |
| 179 if "standalone" in module: | 161 if "standalone" in module: |
| 180 standalone_modules_by_name[name] = module | 162 standalone_modules_by_name[name] = module |
| 181 for dep in module["dependencies"]: | 163 for dep in module.get("dependencies", []): |
| 182 list = dependents_by_module_name.get(dep) | 164 list = dependents_by_module_name.get(dep) |
| 183 if not list: | 165 if not list: |
| 184 list = [] | 166 list = [] |
| 185 dependents_by_module_name[dep] = list | 167 dependents_by_module_name[dep] = list |
| 186 list.append(name) | 168 list.append(name) |
| 187 | 169 |
| 188 | 170 |
| 189 def verify_standalone_modules(): | 171 def verify_standalone_modules(): |
| 190 for module in modules: | 172 for name in modules_by_name: |
| 191 for dependency in module["dependencies"]: | 173 for dependency in modules_by_name[name].get("dependencies", []): |
| 192 if dependency in standalone_modules_by_name: | 174 if dependency in standalone_modules_by_name: |
| 193 log_error("Standalone module '%s' may not be present among the d
ependencies of '%s'" % (dependency, module["name"])) | 175 log_error("Standalone module '%s' may not be present among the d
ependencies of '%s'" % (dependency, name)) |
| 194 errors_found = True | 176 errors_found = True |
| 195 | 177 |
| 196 verify_standalone_modules() | 178 verify_standalone_modules() |
| 197 | 179 |
| 198 | 180 |
| 199 def check_duplicate_files(): | 181 def check_duplicate_files(): |
| 200 | 182 |
| 201 def check_module(module, seen_files, seen_modules): | 183 def check_module(module, seen_files, seen_modules): |
| 202 name = module["name"] | 184 name = module["name"] |
| 203 seen_modules[name] = True | 185 seen_modules[name] = True |
| 204 for dep_name in module["dependencies"]: | 186 for dep_name in module.get("dependencies", []): |
| 205 if not dep_name in seen_modules: | 187 if not dep_name in seen_modules: |
| 206 check_module(modules_by_name[dep_name], seen_files, seen_modules
) | 188 check_module(modules_by_name[dep_name], seen_files, seen_modules
) |
| 207 for source in module["sources"]: | 189 for source in module.get("scripts", []): |
| 208 referencing_module = seen_files.get(source) | 190 referencing_module = seen_files.get(source) |
| 209 if referencing_module: | 191 if referencing_module: |
| 210 log_error("Duplicate use of %s in '%s' (previously seen in '%s')
" % (source, name, referencing_module)) | 192 log_error("Duplicate use of %s in '%s' (previously seen in '%s')
" % (source, name, referencing_module)) |
| 211 seen_files[source] = name | 193 seen_files[source] = name |
| 212 | 194 |
| 213 for module_name in standalone_modules_by_name: | 195 for module_name in standalone_modules_by_name: |
| 214 check_module(standalone_modules_by_name[module_name], {}, {}) | 196 check_module(standalone_modules_by_name[module_name], {}, {}) |
| 215 | 197 |
| 216 print "Checking duplicate files across modules..." | 198 print "Checking duplicate files across modules..." |
| 217 check_duplicate_files() | 199 check_duplicate_files() |
| 218 | 200 |
| 219 | 201 |
| 220 def module_arg(module_name): | 202 def module_arg(module_name): |
| 221 return " --module " + jsmodule_name_prefix + module_name | 203 return " --module " + jsmodule_name_prefix + module_name |
| 222 | 204 |
| 223 | 205 |
| 224 def dump_module(name, recursively, processed_modules): | 206 def dump_module(name, recursively, processed_modules): |
| 225 if name in processed_modules: | 207 if name in processed_modules: |
| 226 return "" | 208 return "" |
| 227 processed_modules[name] = True | 209 processed_modules[name] = True |
| 228 module = modules_by_name[name] | 210 module = modules_by_name[name] |
| 211 skipped_scripts = set(module.get("skip_compilation", [])) |
| 212 |
| 213 def filter_scripts(): |
| 214 result = [] |
| 215 for script in module.get("scripts", []): |
| 216 if script in skipped_scripts: |
| 217 continue |
| 218 result.append(script) |
| 219 return result |
| 220 |
| 229 command = "" | 221 command = "" |
| 230 if recursively: | 222 if recursively: |
| 231 for dependency in module["dependencies"]: | 223 for dependency in module.get("dependencies", []): |
| 232 command += dump_module(dependency, recursively, processed_modules) | 224 command += dump_module(dependency, recursively, processed_modules) |
| 233 command += module_arg(module["name"]) + ":" | 225 command += module_arg(name) + ":" |
| 234 command += str(len(module["sources"])) | 226 filtered_scripts = filter_scripts() |
| 227 command += str(len(filtered_scripts)) |
| 235 firstDependency = True | 228 firstDependency = True |
| 236 for dependency in module["dependencies"] + [runtime_module_name]: | 229 for dependency in module.get("dependencies", []) + [runtime_module_name]: |
| 237 if firstDependency: | 230 if firstDependency: |
| 238 command += ":" | 231 command += ":" |
| 239 else: | 232 else: |
| 240 command += "," | 233 command += "," |
| 241 firstDependency = False | 234 firstDependency = False |
| 242 command += jsmodule_name_prefix + dependency | 235 command += jsmodule_name_prefix + dependency |
| 243 for script in module["sources"]: | 236 for script in filtered_scripts: |
| 244 command += " --js " + path.join(devtools_frontend_path, script) | 237 command += " --js " + path.join(devtools_frontend_path, name, script) |
| 245 return command | 238 return command |
| 246 | 239 |
| 247 print "Compiling frontend..." | 240 print "Compiling frontend..." |
| 248 | 241 |
| 249 compiler_args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False) | 242 compiler_args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False) |
| 250 closure_runner_command = "%s -jar %s --compiler-args-file %s" % (java_exec, clos
ure_runner_jar, compiler_args_file.name) | 243 try: |
| 244 closure_runner_command = "%s -jar %s --compiler-args-file %s" % (java_exec,
closure_runner_jar, compiler_args_file.name) |
| 245 |
| 246 for name in descriptors.sorted_modules(): |
| 247 closure_args = common_closure_args |
| 248 closure_args += " --externs " + global_externs_file |
| 249 closure_args += " --externs " + protocol_externs_file |
| 250 runtime_module = module_arg(runtime_module_name) + ":1 --js " + path.joi
n(devtools_frontend_path, "Runtime.js") |
| 251 closure_args += runtime_module + dump_module(name, True, {}) |
| 252 compiler_args_file.write("%s %s\n" % (name, closure_args)) |
| 253 finally: |
| 254 compiler_args_file.close() |
| 251 | 255 |
| 252 for module in modules: | |
| 253 closure_args = common_closure_args | |
| 254 closure_args += " --externs " + global_externs_file | |
| 255 closure_args += " --externs " + protocol_externs_file | |
| 256 runtime_module = module_arg(runtime_module_name) + ":1 --js " + path.join(de
vtools_frontend_path, "Runtime.js") | |
| 257 closure_args += runtime_module + dump_module(module["name"], True, {}) | |
| 258 compiler_args_file.write("%s %s\n" % (module["name"], closure_args)) | |
| 259 | |
| 260 compiler_args_file.close() | |
| 261 modular_compiler_proc = run_in_shell(closure_runner_command) | 256 modular_compiler_proc = run_in_shell(closure_runner_command) |
| 262 | 257 |
| 263 | 258 |
| 264 def unclosure_injected_script(sourceFileName, outFileName): | 259 def unclosure_injected_script(sourceFileName, outFileName): |
| 265 with open(sourceFileName, "r") as sourceFile: | 260 with open(sourceFileName, "r") as sourceFile: |
| 266 source = sourceFile.read() | 261 source = sourceFile.read() |
| 267 | 262 |
| 268 def replace_function(matchobj): | 263 def replace_function(matchobj): |
| 269 return re.sub(r"@param", "param", matchobj.group(1) or "") + "\n//" + ma
tchobj.group(2) | 264 return re.sub(r"@param", "param", matchobj.group(1) or "") + "\n//" + ma
tchobj.group(2) |
| 270 | 265 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 errors_found |= hasErrors(validateInjectedScriptOut) | 377 errors_found |= hasErrors(validateInjectedScriptOut) |
| 383 | 378 |
| 384 if errors_found: | 379 if errors_found: |
| 385 print "ERRORS DETECTED" | 380 print "ERRORS DETECTED" |
| 386 | 381 |
| 387 os.remove(injectedScriptSourceTmpFile) | 382 os.remove(injectedScriptSourceTmpFile) |
| 388 os.remove(injectedScriptCanvasModuleSourceTmpFile) | 383 os.remove(injectedScriptCanvasModuleSourceTmpFile) |
| 389 os.remove(compiler_args_file.name) | 384 os.remove(compiler_args_file.name) |
| 390 os.remove(protocol_externs_file) | 385 os.remove(protocol_externs_file) |
| 391 shutil.rmtree(modules_dir, True) | 386 shutil.rmtree(modules_dir, True) |
| OLD | NEW |