Chromium Code Reviews| Index: lib/boot.js |
| diff --git a/lib/boot.js b/lib/boot.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..694e51cf4c934e907d30c27974085871a947a0c1 |
| --- /dev/null |
| +++ b/lib/boot.js |
| @@ -0,0 +1,175 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +// This script dynamically prepares a set of files to run polymer.dart. It uses |
| +// the html_import polyfill to search for all imported files, then |
| +// it inlines all <polymer-element> definitions on the top-level page (needed by |
| +// registerPolymerElement), and it removes script tags that appear inside |
| +// those tags. It finally rewrites the main entrypoint to call an initialization |
| +// function on each of the declared <polymer-elements>. |
| +// |
| +// This script is needed only when running polymer.dart in Dartium. It should be |
| +// removed by the polymer deployment commands. |
| + |
| +// As an example, given an input of this form: |
| +// <polymer-element name="c1"> |
| +// <template></template> |
| +// <script type="application/dart" src="url0.dart"></script> |
| +// </polymer-element> |
| +// <element name="c2"> |
| +// <template></template> |
| +// <script type="application/dart">main() => { print('body2'); }</script> |
| +// </element> |
| +// <c1></c1> |
| +// <c2></c2> |
| +// <script type="application/dart" src="url2.dart"></script> |
| +// <script src="packages/polymer/boot.js"></script> |
| +// |
| +// This script will simplifies the page as follows: |
| +// <polymer-element name="c1"> |
| +// <template></template> |
| +// </polymer-element> |
| +// <polymer-element name="c2"> |
| +// <template></template> |
| +// </polymer-element> |
| +// <c1></c1> |
| +// <c2></c2> |
| +// <script type="application/dart"> |
| +// import 'url0.dart' as i0; |
| +// import "data:application/dart;base64,CiAgICBtYWluKCkgewogICAgICBwcmludCgnYm9keTInKTsKICAgIH0KICAgIA==" as i1; |
| +// import 'url2.dart' as i2; |
| +// ... |
| +// main() { |
| +// // code that checks which libraries have a 'main' and invokes them. |
| +// // practically equivalent to: i0._init(); i1._init(); i2.main(); |
| +// } |
| +// </script> |
| + |
| + |
| +(function() { |
| + // Only run in Dartium. |
| + if (!navigator.webkitStartDart) return; |
|
Jennifer Messerly
2013/07/27 02:18:44
should we print a console message?
"boot.js only
Siggi Cherem (dart-lang)
2013/07/30 00:10:29
Done.
|
| + |
| + // Whether [node] is under `<body>` or `<head>` and not nested in an |
| + // `<element>` or `<polymer-element>` tag. |
| + function isTopLevel(node) { |
| + var parent = node.parentNode; |
| + if (parent == null || parent == document.body || parent == document.head) { |
| + return true; |
| + } |
| + if (parent.localName && ( |
| + parent.localName == 'element' || |
| + parent.localName == 'polymer-element')) { |
| + return false; |
| + } |
| + return isTopLevel(parent); |
| + } |
| + |
| + // Extract a Dart import URL from a script tag, which is the 'src' attribute |
| + // of the script tag, or a data-url with the script contents for inlined code. |
| + function getScriptUrl(script) { |
| + var url = script.src; |
| + if (url && url != '') { |
|
Jennifer Messerly
2013/07/27 02:18:44
second check is unnecessary, empty string is false
Siggi Cherem (dart-lang)
2013/07/30 00:10:29
Done.
|
| + // Normalize package: urls |
| + var index = url.indexOf('packages/'); |
| + if (index == 0 || (index > 0 && url[index - 1] == '/')) { |
| + url = "package:" + url.slice(index + 9); |
| + } |
| + |
| + // TODO(sigmund): remove the timestamp. We added this to work around |
|
Jennifer Messerly
2013/07/27 02:18:44
awesome workaround, btw!
|
| + // a caching bug in dartium (see http://dartbug.com/12074). Note this |
| + // doesn't fix caching problems with other libraries imported further in, |
| + // and it can also introduce canonicalization problems if the files under |
| + // these urls are being imported from other libraries. |
| + var time = new Date().getTime(); |
| + return url + '?' + time; |
| + } else { |
| + // TODO(sigmund): investigate how to eliminate the warning in Dartium |
|
Jennifer Messerly
2013/07/27 02:18:44
curious, what is the warning?
Siggi Cherem (dart-lang)
2013/07/30 00:10:29
In the console you'd see a message of this form:
|
| + // (changing to text/javascript hides the warning, but seems wrong). |
| + return "data:application/dart;base64," + window.btoa(script.textContent); |
| + } |
| + } |
| + |
| + // Moves <polymer-elements> from imported documents into the top-level page. |
|
Jennifer Messerly
2013/07/27 02:18:44
does html_imports/polymer do this too?
instead of
Siggi Cherem (dart-lang)
2013/07/30 00:10:29
Exactly =), I was planning to do so as a next step
|
| + function inlinePolymerElements(content, seen) { |
| + if (!seen) seen = {}; |
| + var links = content.querySelectorAll('link[rel="import"]'); |
| + |
| + if (content != document) { // no need to do anything for the top-level page |
| + var elements = content.querySelectorAll('polymer-element'); |
| + var ref = document.body.firstChild; |
| + for (var i = 0; i < elements.length; ++i) { |
| + document.body.insertBefore(elements[i], ref); |
| + } |
| + } |
| + |
| + for (var i = 0; i < links.length; i++) { |
| + var link = links[i].import; |
| + if (seen[link.href]) continue; |
| + seen[link.href] = link; |
| + inlinePolymerElements(link.content, seen); |
| + } |
| + } |
| + |
| + // Creates a Dart program that imports [urls] and [mainUrl] and invokes the |
| + // _init methods of each library in urls (if present) followed by the main |
| + // method of [mainUrl]. |
| + function createMain(urls, mainUrl) { |
| + var imports = Array(urls.length + 2); |
| + for (var i = 0; i < urls.length; ++i) { |
| + imports[i] = 'import "' + urls[i] + '" as i' + i + ';'; |
| + } |
| + imports[urls.length] = 'import "package:polymer/polymer.dart" as polymer;'; |
| + imports[urls.length + 1 ] = 'import "' + mainUrl + '" as userMain;'; |
| + return (imports.join('\n') + |
| + '\n\nmain() {\n' + |
| + ' polymer.initializePolymer([\n' + |
| + ' "' + urls.join('",\n "') + '"\n ], userMain.main);\n' + |
| + '}\n'); |
| + } |
| + |
| + // Finds all top-level <script> tags, and <script> tags in custom elements |
| + // and merges them into a single entrypoint. |
| + function mergeScripts() { |
| + var scripts = document.getElementsByTagName("script"); |
| + var length = scripts.length; |
| + |
| + var dartScripts = [] |
| + var urls = []; |
| + |
| + // Collect the information we need to replace the script tags |
| + for (var i = 0; i < length; ++i) { |
| + var script = scripts[i]; |
| + if (script.type == "application/dart") { |
| + dartScripts.push(script); |
| + if (isTopLevel(script)) continue; |
| + urls.push(getScriptUrl(script)); |
| + } |
| + } |
| + |
| + if (urls.length > 0) { |
| + // Removes all the original script tags under elements, and replace |
| + // top-level script tags so we first call each element's _init. |
| + for (var i = 0; i < dartScripts.length; ++i) { |
| + var script = dartScripts[i]; |
| + if (isTopLevel(script)) { |
| + var newScript = document.createElement('script'); |
| + newScript.type = "application/dart"; |
| + newScript.textContent = createMain(urls, getScriptUrl(script)); |
| + script.parentNode.replaceChild(newScript, script); |
| + } else { |
| + script.parentNode.removeChild(script); |
| + } |
| + } |
| + } |
| + } |
| + |
| + window.addEventListener('HTMLImportsLoaded', function (e) { |
| + inlinePolymerElements(document); |
| + mergeScripts(); |
| + if (!navigator.webkitStartDart()) { |
| + document.body.innerHTML = 'This build has expired. Please download a new Dartium at http://www.dartlang.org/dartium/index.html'; |
| + } |
| + }); |
| +})(); |