| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // This script dynamically prepares a set of files to run polymer.dart. It uses | |
| 6 // the html_import polyfill to search for all imported files, then | |
| 7 // it inlines all <polymer-element> definitions on the top-level page (needed by | |
| 8 // registerPolymerElement), and it removes script tags that appear inside | |
| 9 // those tags. It finally rewrites the main entrypoint to call an initialization | |
| 10 // function on each of the declared <polymer-elements>. | |
| 11 // | |
| 12 // This script is needed only when running polymer.dart in Dartium. It should be | |
| 13 // removed by the polymer deployment commands. | |
| 14 | |
| 15 // As an example, given an input of this form: | |
| 16 // <polymer-element name="c1"> | |
| 17 // <template></template> | |
| 18 // <script type="application/dart" src="url0.dart"></script> | |
| 19 // </polymer-element> | |
| 20 // <element name="c2"> | |
| 21 // <template></template> | |
| 22 // <script type="application/dart">main() => { print('body2'); }</script> | |
| 23 // </element> | |
| 24 // <c1></c1> | |
| 25 // <c2></c2> | |
| 26 // <script type="application/dart" src="url2.dart"></script> | |
| 27 // <script src="packages/polymer/boot.js"></script> | |
| 28 // | |
| 29 // This script will simplifies the page as follows: | |
| 30 // <polymer-element name="c1"> | |
| 31 // <template></template> | |
| 32 // </polymer-element> | |
| 33 // <polymer-element name="c2"> | |
| 34 // <template></template> | |
| 35 // </polymer-element> | |
| 36 // <c1></c1> | |
| 37 // <c2></c2> | |
| 38 // <script type="application/dart"> | |
| 39 // import 'url0.dart' as i0; | |
| 40 // import "data:application/dart;base64,CiAgICBtYWluKCkgewogICAgICBwcmludCgn
Ym9keTInKTsKICAgIH0KICAgIA==" as i1; | |
| 41 // import 'url2.dart' as i2; | |
| 42 // ... | |
| 43 // main() { | |
| 44 // // code that checks which libraries have a 'main' and invokes them. | |
| 45 // // practically equivalent to: i0._init(); i1._init(); i2.main(); | |
| 46 // } | |
| 47 // </script> | |
| 48 | |
| 49 | |
| 50 (function() { | 5 (function() { |
| 51 // Only run in Dartium. | 6 console.error('"boot.js" is now deprecated. Instead, you can initialize ' |
| 52 if (!navigator.webkitStartDart) { | 7 + 'your polymer application by adding the following tags: \'' + |
| 53 // TODO(sigmund): rephrase when we split build.dart in two: analysis vs | 8 + '<script type="application/dart" src="packages/polymer/init.dart">' |
| 54 // deploy pieces. | 9 + '</script><script src="packages/browser/dart.js"></script>\'. ' |
| 55 console.warn('boot.js only works in Dartium. Run the build.dart' + | 10 + 'Make sure these script tags come after all HTML imports.'); |
| 56 ' tool to compile a deployable JavaScript version') | |
| 57 return; | |
| 58 } | |
| 59 | |
| 60 // Detect if dart.js was included in the page. We use DOMContentLoaded to make | |
| 61 // sure we also check for occurrences after the current tag. | |
| 62 window.addEventListener('DOMContentLoaded', function () { | |
| 63 var dartJSQuery = 'script[src="packages/browser/dart.js"]'; | |
| 64 if (!!document.querySelector(dartJSQuery)) { | |
| 65 console.error('Error: found "packages/browser/dart.js" in the ' + | |
| 66 'page. Please remove it. When using polymer\'s "boot.js", ' + | |
| 67 'you can\'t use "dart.js".'); | |
| 68 } | |
| 69 }); | |
| 70 | |
| 71 // Load HTML Imports: | |
| 72 var htmlImportsSrc = 'src="packages/html_import/html_import.min.js"'; | |
| 73 var htmlImportsTag = '<script ' + htmlImportsSrc + '></script>'; | |
| 74 var importScript = document.querySelector('script[' + htmlImportsSrc + ']'); | |
| 75 | |
| 76 if (!importScript) { | |
| 77 try { | |
| 78 document.write(htmlImportsTag); | |
| 79 importScript = document.querySelector('script[' + htmlImportsSrc + ']'); | |
| 80 } catch (e) { | |
| 81 console.error( | |
| 82 "Failed to use document.write() to inject the HTML import " + | |
| 83 "polyfill.\nIf you are running with Content Security Policy, " + | |
| 84 "try adding the following to your HTML's <head> BEFORE the " + | |
| 85 "line that includes polymer/boot.js:\n " + htmlImportsTag); | |
| 86 return; | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 importScript.addEventListener('load', function() { | |
| 91 // NOTE: this is from polymer/src/lib/dom.js | |
| 92 window.HTMLImports.importer.preloadSelectors += | |
| 93 ', polymer-element link[rel=stylesheet]'; | |
| 94 }); | |
| 95 | |
| 96 // TODO(jmesserly): we need this in deploy tool too. | |
| 97 // NOTE: this is from polymer/src/boot.js: | |
| 98 // FOUC prevention tactic | |
| 99 var style = document.createElement('style'); | |
| 100 style.textContent = 'body {opacity: 0;}'; | |
| 101 var head = document.querySelector('head'); | |
| 102 head.insertBefore(style, head.firstChild); | |
| 103 | |
| 104 window.addEventListener('WebComponentsReady', function() { | |
| 105 document.body.style.webkitTransition = 'opacity 0.3s'; | |
| 106 document.body.style.opacity = 1; | |
| 107 }); | |
| 108 | |
| 109 // Extract a Dart import URL from a script tag, which is the 'src' attribute | |
| 110 // of the script tag, or a data-url with the script contents for inlined code. | |
| 111 function getScriptUrl(script) { | |
| 112 var url = script.src; | |
| 113 if (url) { | |
| 114 // Normalize package: urls | |
| 115 var index = url.indexOf('packages/'); | |
| 116 if (index == 0 || (index > 0 && url[index - 1] == '/')) { | |
| 117 url = "package:" + url.slice(index + 9); | |
| 118 } | |
| 119 return url; | |
| 120 } else { | |
| 121 // TODO(sigmund): investigate how to eliminate the warning in Dartium | |
| 122 // (changing to text/javascript hides the warning, but seems wrong). | |
| 123 return "data:application/dart;base64," + window.btoa(script.textContent); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 // Moves <polymer-elements> from imported documents into the top-level page. | |
| 128 function inlinePolymerElements(content, ref, seen) { | |
| 129 if (!seen) seen = {}; | |
| 130 var links = content.querySelectorAll('link[rel="import"]'); | |
| 131 for (var i = 0; i < links.length; i++) { | |
| 132 var link = links[i]; | |
| 133 // TODO(jmesserly): figure out why ".import" fails in content_shell but | |
| 134 // works in Dartium. | |
| 135 if (link.import && link.import.href) link = link.import; | |
| 136 | |
| 137 if (seen[link.href]) continue; | |
| 138 seen[link.href] = link; | |
| 139 inlinePolymerElements(link.content, ref, seen); | |
| 140 } | |
| 141 | |
| 142 if (content != document) { // no need to do anything for the top-level page | |
| 143 var elements = content.querySelectorAll('polymer-element'); | |
| 144 for (var i = 0; i < elements.length; i++) { | |
| 145 document.body.insertBefore(elements[i], ref); | |
| 146 } | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 // Creates a Dart program that imports [urls] and passes them to initPolymer | |
| 151 // (which in turn will invoke their main function, their methods marked with | |
| 152 // @initMethod, and register any custom tag labeled with @CustomTag). | |
| 153 function createMain(urls, mainUrl) { | |
| 154 var imports = Array(urls.length + 1); | |
| 155 for (var i = 0; i < urls.length; ++i) { | |
| 156 imports[i] = 'import "' + urls[i] + '" as i' + i + ';'; | |
| 157 } | |
| 158 imports[urls.length] = 'import "package:polymer/polymer.dart" as polymer;'; | |
| 159 var arg = urls.length == 0 ? '[]' : | |
| 160 ('[\n "' + urls.join('",\n "') + '"\n ]'); | |
| 161 return (imports.join('\n') + | |
| 162 '\n\nmain() {\n' + | |
| 163 ' polymer.initPolymer(' + arg + ');\n' + | |
| 164 '}\n'); | |
| 165 } | |
| 166 | |
| 167 // Finds all top-level <script> tags, and <script> tags in custom elements | |
| 168 // and merges them into a single entrypoint. | |
| 169 function mergeScripts() { | |
| 170 var scripts = document.getElementsByTagName("script"); | |
| 171 var length = scripts.length; | |
| 172 | |
| 173 var urls = []; | |
| 174 var toRemove = []; | |
| 175 | |
| 176 // Collect the information we need to replace the script tags | |
| 177 for (var i = 0; i < length; ++i) { | |
| 178 var script = scripts[i]; | |
| 179 if (script.type == "application/dart") { | |
| 180 urls.push(getScriptUrl(script)); | |
| 181 toRemove.push(script); | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 toRemove.forEach(function (s) { s.parentNode.removeChild(s); }); | |
| 186 | |
| 187 // Append a new script tag that initializes everything. | |
| 188 var newScript = document.createElement('script'); | |
| 189 newScript.type = "application/dart"; | |
| 190 newScript.textContent = createMain(urls); | |
| 191 document.body.appendChild(newScript); | |
| 192 } | |
| 193 | |
| 194 var alreadyRan = false; | |
| 195 window.addEventListener('HTMLImportsLoaded', function (e) { | |
| 196 if (alreadyRan) { | |
| 197 console.warn('HTMLImportsLoaded fired again.'); | |
| 198 return; | |
| 199 } | |
| 200 alreadyRan = true; | |
| 201 var ref = document.body.children[0]; | |
| 202 inlinePolymerElements(document, ref); | |
| 203 mergeScripts(); | |
| 204 if (!navigator.webkitStartDart()) { | |
| 205 document.body.innerHTML = 'This build has expired. Please download a ' + | |
| 206 'new Dartium at http://www.dartlang.org/dartium/index.html'; | |
| 207 } | |
| 208 }); | |
| 209 })(); | 11 })(); |
| OLD | NEW |