The Great Blink mv for source files, part 2.
Move and rename files.
NOAUTOREVERT=true
NOPRESUBMIT=true
NOTREECHECKS=true
Bug: 768828
TBR=darin@chromium.org
NOTRY=true
Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28
Reviewed-on: https://chromium-review.googlesource.com/1001153
Reviewed-by: Blink Reformat <blink-reformat@chromium.org>
Commit-Queue: Blink Reformat <blink-reformat@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#549061}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
diff --git a/scripts/compile_frontend.py b/scripts/compile_frontend.py
new file mode 100755
index 0000000..1c45aa0
--- /dev/null
+++ b/scripts/compile_frontend.py
@@ -0,0 +1,390 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import argparse
+import os
+import os.path as path
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+
+from build import modular_build
+from build import generate_protocol_externs
+
+import dependency_preprocessor
+import utils
+
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+is_cygwin = sys.platform == 'cygwin'
+
+
+def popen(arguments):
+ return subprocess.Popen(arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+def to_platform_path(filepath):
+ if not is_cygwin:
+ return filepath
+ return re.sub(r'^/cygdrive/(\w)', '\\1:', filepath)
+
+
+def to_platform_path_exact(filepath):
+ if not is_cygwin:
+ return filepath
+ output, _ = popen(['cygpath', '-w', filepath]).communicate()
+ # pylint: disable=E1103
+ return output.strip().replace('\\', '\\\\')
+
+
+scripts_path = path.dirname(path.abspath(__file__))
+devtools_path = path.dirname(scripts_path)
+inspector_path = path.join(path.dirname(devtools_path), 'core', 'inspector')
+# TODO(dgozman): move these checks to v8.
+v8_inspector_path = path.normpath(path.join(path.dirname(devtools_path), os.pardir, os.pardir, os.pardir, 'v8', 'src', 'inspector'))
+devtools_frontend_path = path.join(devtools_path, 'front_end')
+global_externs_file = to_platform_path(path.join(devtools_frontend_path, 'externs.js'))
+protocol_externs_file = path.join(devtools_frontend_path, 'protocol_externs.js')
+runtime_file = to_platform_path(path.join(devtools_frontend_path, 'Runtime.js'))
+
+closure_compiler_jar = to_platform_path(path.join(scripts_path, 'closure', 'compiler.jar'))
+closure_runner_jar = to_platform_path(path.join(scripts_path, 'closure', 'closure_runner', 'closure_runner.jar'))
+jsdoc_validator_jar = to_platform_path(path.join(scripts_path, 'jsdoc_validator', 'jsdoc_validator.jar'))
+
+type_checked_jsdoc_tags_list = ['param', 'return', 'type', 'enum']
+type_checked_jsdoc_tags_or = '|'.join(type_checked_jsdoc_tags_list)
+
+# 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).
+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])[^/]*\}')
+invalid_type_designator_regex = re.compile(r'@(?:' + type_checked_jsdoc_tags_or + r')\s*.*(?<![{: ])([?!])=?\}')
+invalid_non_object_type_regex = re.compile(r'@(?:' + type_checked_jsdoc_tags_or + r')\s*\{.*(![a-z]+)[^/]*\}')
+error_warning_regex = re.compile(r'WARNING|ERROR')
+loaded_css_regex = re.compile(r'(?:registerRequiredCSS|WebInspector\.View\.createStyleElement)\s*\(\s*"(.+)"\s*\)')
+
+java_build_regex = re.compile(r'\w+ version "(\d+)\.(\d+)')
+
+
+def log_error(message):
+ print 'ERROR: ' + message
+
+
+def error_excepthook(exctype, value, traceback):
+ print 'ERROR:'
+ sys.__excepthook__(exctype, value, traceback)
+
+
+sys.excepthook = error_excepthook
+
+application_descriptors = [
+ 'inspector',
+ 'toolbox',
+ 'integration_test_runner',
+ 'formatter_worker',
+ 'heap_snapshot_worker',
+]
+
+skipped_namespaces = {
+ 'Console', # Closure uses Console as a namespace item so we cannot override it right now.
+ 'Gonzales', # third party module defined in front_end/externs.js
+ 'Terminal', # third party module defined in front_end/externs.js
+}
+
+
+def has_errors(output):
+ return re.search(error_warning_regex, output) != None
+
+
+class JSDocChecker:
+
+ def __init__(self, descriptors, java_exec):
+ self._error_found = False
+ self._all_files = descriptors.all_compiled_files()
+ self._java_exec = java_exec
+
+ def check(self):
+ print 'Verifying JSDoc comments...'
+ self._verify_jsdoc()
+ self._run_jsdoc_validator()
+ return self._error_found
+
+ def _run_jsdoc_validator(self):
+ files = [to_platform_path(f) for f in self._all_files]
+ file_list = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ try:
+ file_list.write('\n'.join(files))
+ finally:
+ file_list.close()
+ proc = popen(self._java_exec + ['-jar', jsdoc_validator_jar, '--files-list-name', to_platform_path_exact(file_list.name)])
+ (out, _) = proc.communicate()
+ if out:
+ print('JSDoc validator output:%s%s' % (os.linesep, out))
+ self._error_found = True
+ os.remove(file_list.name)
+
+ def _verify_jsdoc(self):
+ for full_file_name in self._all_files:
+ line_index = 0
+ with open(full_file_name, 'r') as sourceFile:
+ for line in sourceFile:
+ line_index += 1
+ if line.rstrip():
+ self._verify_jsdoc_line(full_file_name, line_index, line)
+
+ def _verify_jsdoc_line(self, file_name, line_index, line):
+
+ def print_error(message, error_position):
+ print '%s:%s: ERROR - %s%s%s%s%s%s' % (file_name, line_index, message, os.linesep, line, os.linesep,
+ ' ' * error_position + '^', os.linesep)
+
+ known_css = {}
+ match = re.search(invalid_type_regex, line)
+ if match:
+ print_error('Type "%s" nullability not marked explicitly with "?" (nullable) or "!" (non-nullable)' % match.group(1),
+ match.start(1))
+ self._error_found = True
+
+ match = re.search(invalid_non_object_type_regex, line)
+ if match:
+ print_error('Non-object type explicitly marked with "!" (non-nullable), which is the default and should be omitted',
+ match.start(1))
+ self._error_found = True
+
+ match = re.search(invalid_type_designator_regex, line)
+ if match:
+ print_error('Type nullability indicator misplaced, should precede type', match.start(1))
+ self._error_found = True
+
+ match = re.search(loaded_css_regex, line)
+ if match:
+ file = path.join(devtools_frontend_path, match.group(1))
+ exists = known_css.get(file)
+ if exists is None:
+ exists = path.isfile(file)
+ known_css[file] = exists
+ if not exists:
+ print_error('Dynamically loaded CSS stylesheet is missing in the source tree', match.start(1))
+ self._error_found = True
+
+
+def find_java():
+ required_major = 1
+ required_minor = 7
+ exec_command = None
+ has_server_jvm = True
+ java_path = utils.which('java')
+
+ if not java_path:
+ print 'NOTE: No Java executable found in $PATH.'
+ sys.exit(1)
+
+ is_ok = False
+ java_version_out, _ = popen([java_path, '-version']).communicate()
+ # pylint: disable=E1103
+ match = re.search(java_build_regex, java_version_out)
+ if match:
+ major = int(match.group(1))
+ minor = int(match.group(2))
+ is_ok = major >= required_major and minor >= required_minor
+ if is_ok:
+ exec_command = [java_path, '-Xms1024m', '-server', '-XX:+TieredCompilation']
+ check_server_proc = popen(exec_command + ['-version'])
+ check_server_proc.communicate()
+ if check_server_proc.returncode != 0:
+ # Not all Java installs have server JVMs.
+ exec_command = exec_command.remove('-server')
+ has_server_jvm = False
+
+ if not is_ok:
+ print 'NOTE: Java executable version %d.%d or above not found in $PATH.' % (required_major, required_minor)
+ sys.exit(1)
+ print 'Java executable: %s%s' % (java_path, '' if has_server_jvm else ' (no server JVM)')
+ return exec_command
+
+
+common_closure_args = [
+ '--summary_detail_level',
+ '3',
+ '--jscomp_error',
+ 'visibility',
+ '--jscomp_warning',
+ 'missingOverride',
+ '--compilation_level',
+ 'SIMPLE_OPTIMIZATIONS',
+ '--warning_level',
+ 'VERBOSE',
+ '--language_in=ECMASCRIPT_2017',
+ '--language_out=ES5_STRICT',
+ '--extra_annotation_name',
+ 'suppressReceiverCheck',
+ '--extra_annotation_name',
+ 'suppressGlobalPropertiesCheck',
+ '--checks-only',
+ '--allow_method_call_decomposing',
+]
+
+
+def check_conditional_dependencies(modules_by_name):
+ errors_found = False
+ for name in modules_by_name:
+ if 'test_runner' in name:
+ continue
+ for dep_name in modules_by_name[name].get('dependencies', []):
+ dependency = modules_by_name[dep_name]
+ if dependency.get('experiment') or dependency.get('condition'):
+ log_error('Module "%s" may not depend on the conditional module "%s"' % (name, dep_name))
+ errors_found = True
+ return errors_found
+
+
+def prepare_closure_frontend_compile(temp_devtools_path, descriptors, namespace_externs_path):
+ temp_frontend_path = path.join(temp_devtools_path, 'front_end')
+ checker = dependency_preprocessor.DependencyPreprocessor(descriptors, temp_frontend_path, devtools_frontend_path)
+ checker.enforce_dependencies()
+
+ command = common_closure_args + [
+ '--externs',
+ to_platform_path(global_externs_file),
+ '--externs',
+ namespace_externs_path,
+ '--js',
+ runtime_file,
+ ]
+
+ all_files = descriptors.all_compiled_files()
+ args = []
+ for file in all_files:
+ args.extend(['--js', file])
+ if "InspectorBackend.js" in file:
+ args.extend(['--js', protocol_externs_file])
+ command += args
+ command = [arg.replace(devtools_frontend_path, temp_frontend_path) for arg in command]
+ compiler_args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ try:
+ compiler_args_file.write('devtools_frontend %s' % (' '.join(command)))
+ finally:
+ compiler_args_file.close()
+ return compiler_args_file.name
+
+
+def generate_namespace_externs(modules_by_name):
+ special_case_namespaces_path = path.join(path.dirname(path.abspath(__file__)), 'special_case_namespaces.json')
+ with open(special_case_namespaces_path) as json_file:
+ special_case_namespaces = json.load(json_file)
+
+ def map_module_to_namespace(module):
+ return special_case_namespaces.get(module, to_camel_case(module))
+
+ def to_camel_case(snake_string):
+ components = snake_string.split('_')
+ return ''.join(x.title() for x in components)
+
+ all_namespaces = [map_module_to_namespace(module) for module in modules_by_name]
+ namespaces = [namespace for namespace in all_namespaces if namespace not in skipped_namespaces]
+ namespaces.sort()
+ namespace_externs_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ try:
+ for namespace in namespaces:
+ namespace_externs_file.write('/** @const */\n')
+ namespace_externs_file.write('var %s = {};\n' % namespace)
+ finally:
+ namespace_externs_file.close()
+ namespace_externs_path = to_platform_path(namespace_externs_file.name)
+ return namespace_externs_path
+
+
+def main():
+ global protocol_externs_file
+ errors_found = False
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--protocol-externs-file')
+ args, _ = parser.parse_known_args()
+ if args.protocol_externs_file:
+ protocol_externs_file = args.protocol_externs_file
+ else:
+ generate_protocol_externs.generate_protocol_externs(protocol_externs_file,
+ path.join(inspector_path, 'browser_protocol.json'),
+ path.join(v8_inspector_path, 'js_protocol.json'))
+ loader = modular_build.DescriptorLoader(devtools_frontend_path)
+ descriptors = loader.load_applications(application_descriptors)
+ modules_by_name = descriptors.modules
+
+ java_exec = find_java()
+ errors_found |= check_conditional_dependencies(modules_by_name)
+
+ print 'Compiling frontend...'
+ temp_devtools_path = tempfile.mkdtemp()
+ namespace_externs_path = generate_namespace_externs(modules_by_name)
+ compiler_args_file_path = prepare_closure_frontend_compile(temp_devtools_path, descriptors, namespace_externs_path)
+ frontend_compile_proc = popen(
+ java_exec + ['-jar', closure_runner_jar, '--compiler-args-file', to_platform_path_exact(compiler_args_file_path)])
+
+ print 'Compiling devtools_compatibility.js...'
+
+ closure_compiler_command = java_exec + ['-jar', closure_compiler_jar] + common_closure_args
+
+ devtools_js_compile_command = closure_compiler_command + [
+ '--externs', to_platform_path(global_externs_file), '--externs',
+ to_platform_path(path.join(devtools_frontend_path, 'host', 'InspectorFrontendHostAPI.js')),
+ '--jscomp_off=externsValidation', '--js', to_platform_path(path.join(devtools_frontend_path, 'devtools_compatibility.js'))
+ ]
+ devtools_js_compile_proc = popen(devtools_js_compile_command)
+
+ errors_found |= JSDocChecker(descriptors, java_exec).check()
+
+ (devtools_js_compile_out, _) = devtools_js_compile_proc.communicate()
+ print 'devtools_compatibility.js compilation output:%s' % os.linesep, devtools_js_compile_out
+ errors_found |= has_errors(devtools_js_compile_out)
+
+ (frontend_compile_out, _) = frontend_compile_proc.communicate()
+ print 'devtools frontend compilation output:'
+ for line in frontend_compile_out.splitlines():
+ if "@@ START_MODULE" in line or "@@ END_MODULE" in line:
+ continue
+ print line
+ errors_found |= has_errors(frontend_compile_out)
+
+ os.remove(protocol_externs_file)
+ os.remove(namespace_externs_path)
+ os.remove(compiler_args_file_path)
+ shutil.rmtree(temp_devtools_path, True)
+
+ if errors_found:
+ print 'ERRORS DETECTED'
+ sys.exit(1)
+ print 'DONE - compiled without errors'
+
+
+if __name__ == "__main__":
+ main()