Commit bdcdd774 authored by rbpotter's avatar rbpotter Committed by Commit Bot

WebUI: Add option to make optimized pages work with HTMLImports polyfill

Add an option to make Web UI pages work with the HTMLImports polyfill in
optimized builds. This is in preparation for modifying Web UI pages to
work with the polyfill instead of relying on native imports.

Bug: 925517
Change-Id: I8f6ca8694bd73defa810c304f31b83dc5ec7d19c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1566761
Commit-Queue: Rebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#653411}
parent cd8989eb
......@@ -74,6 +74,13 @@ template("optimize_webui") {
invoker.insert_in_head,
]
}
if (defined(invoker.replace_for_html_imports_polyfill)) {
args += [
"--replace-for-html-imports-polyfill",
invoker.replace_for_html_imports_polyfill,
]
}
}
}
......
......@@ -48,6 +48,8 @@ _POLYMER_PATH = os.path.join(
_VULCANIZE_BASE_ARGS = [
# These files are already combined and minified.
'--exclude', 'chrome://resources/html/polymer.html',
'--exclude', 'chrome://resources/polymer/v1_0/html-imports/' +
'html-imports.min.js',
'--exclude', 'chrome://resources/polymer/v1_0/polymer/polymer.html',
'--exclude', 'chrome://resources/polymer/v1_0/polymer/polymer-micro.html',
'--exclude', 'chrome://resources/polymer/v1_0/polymer/polymer-mini.html',
......@@ -193,6 +195,28 @@ def _optimize(in_folder, args):
'--html', crisper_html_out_paths[index],
'--js', os.path.join(tmp_out_dir, js_out_file)])
if args.replace_for_html_imports_polyfill == js_out_file:
# Replace the output file with a loader script, to wait until HTML
# imports are ready before loading.
with open(crisper_html_out_paths[index], 'r') as f:
output = f.read()
output = output.replace(js_out_file + '"',
'chrome://resources/js/crisper_loader.js"' + \
' data-script-name="' + js_out_file + '"')
# Preload the final script, even though it will not be evaluated
# until after crisper_loader.js executes.
output = output.replace('<head>',
'<head><link rel="preload" href="' + \
js_out_file + '" as="script">')
f.close()
# Open file again with 'w' such that the previous contents are
# overwritten.
with open(crisper_html_out_paths[index], 'w') as f:
f.write(output)
f.close()
# Pass the JS file through Uglify and write the output to its final
# destination.
node.RunNode([node_modules.PathToUglify(),
......@@ -224,6 +248,7 @@ def main(argv):
parser.add_argument('--insert_in_head')
parser.add_argument('--js_out_files', nargs='*', required=True)
parser.add_argument('--out_folder', required=True)
parser.add_argument('--replace-for-html-imports-polyfill')
args = parser.parse_args(argv)
# NOTE(dbeam): on Windows, GN can send dirs/like/this. When joined, you might
......
......@@ -44,7 +44,8 @@ class OptimizeWebUiTest(unittest.TestCase):
assert self._out_folder
return open(os.path.join(self._out_folder, file_name), 'r').read()
def _run_optimize(self, depfile, html_in_file, html_out_file, js_out_file):
def _run_optimize(self, depfile, html_in_file, html_out_file, js_out_file,
replace_for_html_imports_polyfill):
# TODO(dbeam): make it possible to _run_optimize twice? Is that useful?
assert not self._out_folder
self._out_folder = self._create_tmp_dir()
......@@ -56,10 +57,10 @@ class OptimizeWebUiTest(unittest.TestCase):
'--input', self._tmp_src_dir,
'--js_out_files', js_out_file,
'--out_folder', self._out_folder,
'--replace-for-html-imports-polyfill', replace_for_html_imports_polyfill,
])
def testSimpleOptimize(self):
def _write_files_to_src_dir(self):
self._write_file_to_src_dir('element.html', '<div>got here!</div>')
self._write_file_to_src_dir('element.js', "alert('yay');")
self._write_file_to_src_dir('element_in_dir/element_in_dir.html',
......@@ -72,23 +73,19 @@ class OptimizeWebUiTest(unittest.TestCase):
<script src="element.js"></script>
''')
self._run_optimize(depfile='depfile.d',
html_in_file='ui.html',
html_out_file='fast.html',
js_out_file='fast.js')
fast_html = self._read_out_file('fast.html')
self.assertNotIn('element.html', fast_html)
self.assertNotIn('element.js', fast_html)
self.assertNotIn('element_in_dir.html', fast_html)
self.assertNotIn('element_in_dir.js', fast_html)
self.assertIn('got here!', fast_html)
self.assertIn('<script src="fast.js"></script>', fast_html)
def _check_output_html(self, out_html):
self.assertNotIn('element.html', out_html)
self.assertNotIn('element.js', out_html)
self.assertNotIn('element_in_dir.html', out_html)
self.assertNotIn('element_in_dir.js', out_html)
self.assertIn('got here!', out_html)
def _check_output_js(self):
fast_js = self._read_out_file('fast.js')
self.assertIn('yay', fast_js)
self.assertIn('hello from element_in_dir', fast_js)
def _check_output_depfile(self):
depfile_d = self._read_out_file('depfile.d')
self.assertIn('element.html', depfile_d)
self.assertIn('element.js', depfile_d)
......@@ -97,6 +94,42 @@ class OptimizeWebUiTest(unittest.TestCase):
self.assertIn(os.path.normpath('element_in_dir/element_in_dir.js'),
depfile_d)
def testSimpleOptimize(self):
self._write_files_to_src_dir()
self._run_optimize(depfile='depfile.d',
html_in_file='ui.html',
html_out_file='fast.html',
js_out_file='fast.js',
replace_for_html_imports_polyfill='')
fast_html = self._read_out_file('fast.html')
self._check_output_html(fast_html)
self.assertIn('<script src="fast.js"></script>', fast_html)
self.assertNotIn(
'<script src="chrome://resources/js/crisper_loader.js"></script>',
fast_html)
self._check_output_js()
self._check_output_depfile()
def testSimpleOptimizeWithHTMLImportsPolyfill(self):
self._write_files_to_src_dir()
self._run_optimize(depfile='depfile.d',
html_in_file='ui.html',
html_out_file='fast.html',
js_out_file='fast.js',
replace_for_html_imports_polyfill='fast.js')
fast_html = self._read_out_file('fast.html')
self._check_output_html(fast_html)
self.assertNotIn('<script src="fast.js"></script>', fast_html)
self.assertIn(
'<script src="chrome://resources/js/crisper_loader.js" ' + \
'data-script-name="fast.js"></script>',
fast_html)
self.assertIn('<link rel="preload" href="fast.js" as="script">',
fast_html)
self._check_output_js()
self._check_output_depfile()
if __name__ == '__main__':
unittest.main()
......@@ -47,6 +47,8 @@
<structure name="IDR_WEBUI_JS_CR_UI_FOCUS_WITHOUT_INK"
file="js/cr/ui/focus_without_ink.js" type="chrome_html"
compress="gzip" />
<structure name="IDR_WEBUI_JS_CRISPER_LOADER"
file="js/crisper_loader.js" type="chrome_html" compress="gzip" />
<structure name="IDR_WEBUI_JS_FIND_SHORTCUT_BEHAVIOR"
file="js/find_shortcut_behavior.js" type="chrome_html"
compress="gzip" />
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* Unlike when using native HTML Imports, the HTML Imports polyfill does not
* block execution of a script until all files have been imported, resulting in
* errors if the script references functions (e.g. Polymer()) from files that
* have not been imported yet. crisper_loader.js is used as a replacement for
* the main script in optimized Web UI pages that are set to use the polyfill
* instead of native imports, and is responsible for replacing itself with the
* main JS file after the polyfill is ready.
*/
(function() {
const thisScript = document.currentScript;
const scriptName = thisScript.dataset.scriptName;
const parentEl = thisScript.parentElement;
const script = document.createElement('script');
script.setAttribute('src', scriptName);
HTMLImports.whenReady(() => {
parentEl.appendChild(script);
thisScript.remove();
});
})();
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment