Index: pkg/polymer/lib/boot.js |
diff --git a/pkg/polymer/lib/boot.js b/pkg/polymer/lib/boot.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..15e43865616746767be633e7837d23667a306e44 |
--- /dev/null |
+++ b/pkg/polymer/lib/boot.js |
@@ -0,0 +1,188 @@ |
+// 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) { |
+ // TODO(sigmund): rephrase when we split build.dart in two: analysis vs |
+ // deploy pieces. |
+ console.warn('boot.js only works in Dartium. Run the build.dart' + |
+ ' tool to compile a depolyable JavaScript version') |
+ return; |
+ } |
+ document.write( |
+ '<script src="packages/html_import/html_import.min.js"></script>'); |
+ |
+ // 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) { |
+ // 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 |
+ // 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 |
+ // (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. |
+ function inlinePolymerElements(content, ref, seen) { |
+ if (!seen) seen = {}; |
+ var links = content.querySelectorAll('link[rel="import"]'); |
+ 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, ref, seen); |
+ } |
+ |
+ if (content != document) { // no need to do anything for the top-level page |
+ var elements = content.querySelectorAll('polymer-element'); |
+ for (var i = 0; i < elements.length; i++) { |
+ document.body.insertBefore(elements[i], ref); |
+ } |
+ } |
+ } |
+ |
+ // 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;'; |
+ var firstArg = urls.length == 0 ? '[]' : |
+ ('[\n "' + urls.join('",\n "') + '"\n ]'); |
+ return (imports.join('\n') + |
+ '\n\nmain() {\n' + |
+ ' polymer.initPolymer(' + firstArg + ', 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)); |
+ } |
+ } |
+ |
+ // 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); |
+ } |
+ } |
+ } |
+ |
+ var alreadyRan = false; |
+ window.addEventListener('HTMLImportsLoaded', function (e) { |
+ if (alreadyRan) { |
+ console.warn('HTMLImportsLoaded fired again.'); |
+ return; |
+ } |
+ alreadyRan = true; |
+ var ref = document.body.children[0]; |
+ inlinePolymerElements(document, ref); |
+ mergeScripts(); |
+ if (!navigator.webkitStartDart()) { |
+ document.body.innerHTML = 'This build has expired. Please download a ' + |
+ 'new Dartium at http://www.dartlang.org/dartium/index.html'; |
+ } |
+ }); |
+})(); |